go generate とは
-
go generate は Go の標準ツール
- コマンドラインから
go generate
と実行.. - するとコードから
//go:generate
から始まるコメント行を検索し//go:generate command argument...
というコメント行の全文からcommand
のコマンドをargument...
の引数付きで実行する - 任意のコマンドを実行できるが Go のコードを生成することを想定して作られている
- コマンドラインから
- 自動では実行されないので、任意のタイミングで手動で実行したり、メイクファイルに記載しておきビルド前に実行したり、ファイル変更を検知して実行したりする
go generate は何をしてくれるか
-
go generate
と実行するとカレントディレクトリから*.go
ファイルを検索して各ファイル毎に//go:generate
から始まるコメント行を探して実行する
// ファイルとディレクトリの作成
$ mkdir g1 g2
$ echo -e 'package g1\n//go:generate echo one' > g1/file1.go
$ echo -e 'package g1\n//go:generate echo two' > g1/file2.go
$ echo -e 'package g2\n//go:generate echo three' > g2/file3.go
// g1 で実行. file1.go file2.go の go:generate コマンドが実行される
$ cd g1
$ go generate
one
two
// g2 で実行. file3.go の go:generate コマンドが実行される
$ cd ../g2
$ go generate
three
$ cd ../
// 親ディレクトリで再帰的に実行. すべてのファイルの go:generate コマンドが実行される
$ go generate ./...
one
two
three
// go:generate コマンド行には実行環境の情報を変数で渡せる
$ mkdir g3
$ echo -e 'package g3\n//go:generate echo $GOARCH -- $GOOS -- $GOFILE -- $GOLINE -- $GOPACKAGE' > g3/file4.go
$ cd g3
$ go generate
amd64 -- darwin -- file4.go -- 2 -- g3
- このように go generate はコマンドを検索して(必要であれば環境を変数で渡して)コマンドを実行してくれるが、コード自体の解析などは行ってくれない。
stringer とは
- stringer とは定数を定数名の文字列に変換する関数を生成するコマンド
-
stringer -type=Pill [file|dir]
とすると file か dir のファイル一覧からPill
型の定数を検索して、定数名の文字列を返すfunc (Pill) String() string
を生成する - file も dir も指定しない場合はカレントディレクトリを dir として実行する
- go generate からは
Pill
型の定数の宣言されたコードかそのコードと同じディレクトリのコードに//go:generate stringer -type=Pill
と記載して実行する
おわりに
- なんとなく自分でも go generate に対応したツールが作れそうな気がしてきた
- コードを検索して解析して生成する流れはある程度パターンがありそうだからジェネレータのジェネレータも作れるかもしれない