Go Generateを使用したコード生成

Go Generateを使用したコード生成

2025年5月15日

image

Goは、特性上ボイラープレートが他の言語に比べて頻繁に発生します。Javaを見ても、一般的なGetter/Setterを作成するためにLombokのようなツールを使用し、モックのためにMockitoのようなツールを使用することができます。

これらの2つのライブラリは、Java Annotation Processorを使用してコードを生成しますが、開発者が直接コードを生成するわけではありません。

一方、GoにはJavaのようなAnnotation Processorがありません。一般的には、コードを生成するためにCLIを直接インストールし、CLIを介してコードを生成する必要があります。 筆者の場合、Swaggerを使用するためにswaggoライブラリを使用しています。このライブラリも内部コードを解析してSwaggerのドキュメントであるdocs.jsonを生成します。

この他にも、GRPCを使用するためにprotocを使用してコードを生成したり、モックインターフェースを使用するためにmockeryを使用してコードを生成したりするなど、さまざまなCLIツールを使用してコードを生成することができます。

Makefileを使用したコード生成

生成時に使用するswagのコマンドは、筆者の場合次のようになります。

swag init -g ./cmd/main.go -o ./docs

毎回このようなコマンドを入力するには記憶力が不足しており、指も面倒なので、一般的にはAliasを使用するか、Makefileのようなツールを使用することになります。

Makefileを使用してコードを生成する方法は次のとおりです。

.PHONY: swag
swag:
    @swag init -g ./cmd/main.go -o ./docs

このようにすると、make swagコマンドを通じてコードを生成することができます。

Go Generateを使用したコード生成

Goもこういった部分に限界を感じたのか、コードを生成するためのツールであるgo generateを提供しています。

Go Generateは、Goソースファイルにコメントとしてコマンドを記述し、該当コマンドを実行してコードを生成するツールです。

例えば、swagを例に挙げると次のように記述できます。

somefile.go
//go:generate swag init -g ./cmd/main.go -o ./docs

このように記述すると、go generate ./somefile.goコマンドを通じてコードを生成することができます。

ファイルを直接指定したくない場合は、以下のようにプロジェクト内のすべてのGoファイルを巡回し、//go:generateがあれば実行するようにコマンドを構成することもできます。

go generate ./...

実務ではこの方法が最も多く使われています。

注意点

Go Generateの実行は、該当ファイルのパスで実行されます。そのため、相対パスを使用する多くのCLIツールはGo Generateを使用する際にパスに注意を払う必要があります。

例えば、次のような構造があり、foo/bar.goファイルにgo:generateがあると仮定しましょう。

foo/bar.go
//go:generate swag init -g ./cmd/main.go -o ./docs
    • bar.go
    • main.go
  • この場合、go generate ./...コマンドを実行すると、./cmd/main.goというパスを見つけられずエラーが発生します。 また、出力パスである./docsも相対パスで書かれているため、foo/docsに生成されます。

    したがって、相対パスを使用する場合は、Go Generateを使用する際には注意が必要です。

    //go:generate swag init -g ../cmd/main.go -o ../docs

    参考文献