導入
Go言語の開発において、コード生成ツール(Mockgen, Protobuf, SQLBoilerなど)は欠かせない存在です。しかし、プロジェクトが大きくなるにつれ、すべての生成コマンドを一度に実行する `go generate ./…` は非常に時間がかかるようになります。修正した箇所に関連する生成処理だけをピンポイントで実行できれば、開発者のフィードバックループは劇的に速くなります。本記事では、`go generate` の限定実行手法について解説します。
基礎知識
`go generate` は、ソースコード内の `//go:generate` コメントをスキャンし、そこに記述されたコマンドを順次実行する仕組みです。通常、プロジェクトルートで実行すると全ファイルを走査しますが、実は `-run` フラグを使うことで、特定のパターンにマッチするコマンドのみを選択的に実行することが可能です。これにより、不要な重い処理(外部APIを叩くコード生成や大規模なスキーマ変換など)をスキップし、高速に開発を進めることができます。
実装/解決策
限定実行を実現するには、`go generate -run <正規表現> ./…` というコマンド構文を使用します。`-run` フラグに渡す正規表現は、`//go:generate` に記述されたコマンド文字列全体に対して評価されます。例えば、Mockgenだけを更新したい場合は `mockgen` という文字列を指定することで、それ以外のコマンド(Protobuf生成など)を無視できます。
サンプルプログラム
以下は、異なるツールを利用しているプロジェクトでの具体的な実行例です。
// プロジェクト内の全generateコマンドを確認し、特定のツールだけを実行する例
// 1. 全ての生成処理を実行(通常時)
// $ go generate ./…
// 2. 正規表現を用いて「mockgen」を含むコマンドのみ実行(高速化)
// $ go generate -run “mockgen” ./…
// 3. 複数のキーワードを指定して実行(例: mockgen または stringer)
// $ go generate -run “mockgen|stringer” ./…
// 以下はソースコード内に記述する generate コメントの例です
package example
// このコマンドは「mockgen」という文字列を含むため、限定実行の対象になります
//go:generate mockgen -source=interface.go -destination=mock_interface.go
// このコマンドは「protoc」を含むため、上の実行コマンドではスキップされます
//go:generate protoc –go_out=. schema.proto
応用・注意点
現場で活用する際のポイントをいくつか挙げます。
1. 正規表現の精緻化
`-run` は部分一致で動作するため、意図しないコマンドまで実行されないよう、できるだけ具体的な文字列を指定してください。例えば単に `gen` と指定すると、`gen-sql` も `generate-mock` もすべて実行されてしまいます。
2. Makefileとの組み合わせ
開発者が毎回正規表現を打つのは手間です。`Makefile` に `make gen-mock` や `make gen-proto` といったターゲットを用意し、その中で `go generate -run “mockgen” ./…` を呼び出すようにすると、チーム全体での開発体験が向上します。
3. 依存関係の考慮
特定の生成物のみを更新する場合、他のファイルとの依存関係が壊れないか注意が必要です。例えば、Protobufの変更がMockに影響を与える場合、片方だけを更新すると型不整合が起きます。限定実行は「修正範囲が局所的であること」が明確な場合にのみ利用するようにしましょう。

コメント