gowrtr で名前付き戻り値を扱う
先日リリースされた gowrtr が非常に便利でめちゃくちゃ助かってます。buf に自分で fmt.Fprintf とかしてたのが懐かしいです。
お気に入りポイントは、immutable なつくりになっているところと、goimports とかをかけた状態で出力できるところです。マジでいい
特に goimports をかけてくれるおかげでパッケージの import 文とかはすげえ適当に書いておいて後からツールに削ってもらうというのが可能になります。makeファイルに後処理書かなくて済んでうれしい。
さて、そんな go-wrtr で func の戻り値を定義しようとすると *FuncSignature
に対して AddReturnTypes
とすることになります。
package main import ( "fmt" "github.com/moznion/gowrtr/generator" ) func main() { g := generator.NewRoot() sig := generator.NewFuncSignature("foo") sig = sig.AddReturnTypes("int32", "error") g = g.AddStatements( generator.NewFunc( nil, sig, generator.NewReturnStatement("1, nil"), ), ) src, err := g.Gofmt("-s").Goimports().Generate(0) if err != nil { panic(err) } fmt.Print(src) }
$ go run tekitou.go func foo() (int32, error) { return 1, nil }
しかし自動生成するときには名前付き戻り値を使いたくなったりします。具体的にはライブラリの関数をラップする関数を書くとき、途中でエラーになったから早期リターンしたいが、各戻り値のデフォルト値を毎回書くのがダルいとかです。
// Foo() (int32, string, err) のようなシグネチャだとして func WrapFoo() (int32, string, error) { err := preprocess() if err != nil { return 0, "", err // ここでデフォルト値を書くのがめんどい } return Foo() } func WrapFoo() (i int32, s string, err error) { err = preprocess() if err != nil { return // こうしたい } return Foo() }
しかし、AddReturnTypes
は string しか受け付けません。これはどうするのかというと AddReturnTypes にそのまま文字列で渡しちゃうのがよさそうです。
package main import ( "fmt" "github.com/moznion/gowrtr/generator" ) func main() { g := generator.NewRoot() sig := generator.NewFuncSignature("foo") sig = sig.AddReturnTypes("i int32", "err error") // 名前も書いちゃう g = g.AddStatements( generator.NewFunc( nil, sig, generator.NewReturnStatement("1, nil"), ), ) src, err := g.Gofmt("-s").Goimports().Generate(0) if err != nil { panic(err) } fmt.Print(src) }
と、ここまで書いたところで気づいたのですが、実は多値を返さずに1つしか return しないときは生成時にエラーになっちゃいますね……。多値のときにお試しください。1
2019-01-21 00:54 ライブラリの名前が間違ってたので直しました(ハイフンとった)
-
パッチ書いてみる予定↩