Posted at

実行例と 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 に対応したツールが作れそうな気がしてきた

  • コードを検索して解析して生成する流れはある程度パターンがありそうだからジェネレータのジェネレータも作れるかもしれない