Go
golang

実行例と stringer から学ぶ go generate 入門

More than 1 year has passed since last update.

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 に対応したツールが作れそうな気がしてきた
  • コードを検索して解析して生成する流れはある程度パターンがありそうだからジェネレータのジェネレータも作れるかもしれない