はじめに
表題のものをリリースしました。
go install コマンドもしくは go get -tool コマンドでインストールして使うことを推奨しています。現代なので go get -tool コマンドを使うのがいいと思います。
どういうツールなのか
たとえば、resolver.go というファイルに以下のようなstruct定義があったとします。各 Usecase 型はinterfaceになっており、対応する実装を何らかの方法で依存注入する必要があります。
type Resolver struct { user user.Usecase blog blog.Usecase entry entry.Usecase comment comment.Usecase }
gosimplectorgenを使って gosimplectorgen resolver.go というコマンドを実行すると、以下のような関数が resolver_gen.go というファイルに生成されます。このように、引数から受け取った値をstructのフィールドに埋めて返す関数のことをコンストラクタ関数と個人的に呼んでいます (以下、この記事内でもそのように呼びます)。
func NewResolver( user user.Usecase, blog blog.Usecase, entry entry.Usecase, comment comment.Usecase, ) *Resolver { return &Resolver{ user: user, blog: blog, entry: entry, comment: comment, } }
基本的な機能はこれだけです。
以下のコマンドライン引数でコード生成の挙動を変えられます。
-out- コードを生成する先のファイル名を指定します
-targetTypes- 渡されたファイルに含まれるstruct型のうち、コンストラクタ関数を生成する対象の型名をカンマ区切りで指定します
- 未指定のときは、ファイルに含まれる全てのstruct型を対象とします
動機
Goでstructに対してinterfaceを経由して依存注入を行う場合、なんらかの方法でstructのフィールドをセットしていくことになると思います。よくあるのが、先述したようにコンストラクタ関数 (structのフィールドを埋めて返す関数) を定義する方法です。
コンストラクタ関数は簡単に定義できますが、以下のような課題を抱えています。
- structリテラルのフィールドの値を埋め忘れて、実行時エラーになる
- struct定義とコンストラクタ関数の定義を両方とも更新する必要があり、二度手間である
前者はたとえばexhaustruct linterで簡単に検査できますが、後者は手書きしているうちはどうしようもありません。VSCodeのGo拡張の機能を使ってstructリテラルのフィールドを自動的に埋めることで多少緩和はできますが、それでも手書きしなければならないものが残ってしまいます。
手書きするとミスの余地があるし、なんだかんだで手間な作業ではあるので、コード生成の力で自動化してしまおう、ということでツールを作りました。
実装
サンプルコードと方針のメモ書きだけを渡してClaude Codeにだいたい実装してもらいました。本質的な実装は200行ちょっとぐらいです。
これぐらいのコードであれば、Goの静的解析を多少かじっていれば手書きできると思うけど、Claude Codeにばしばし実装してもらうほうが早いですね。OSS仕草としてREADMEやコミットメッセージなどを英語で書くようにしているけど、これもClaude Codeに文言を考えてもらったので楽でした。
他のツールとの比較
golang constructor generatorで検索すると、いくつか同様のツールが出てきます。
- GitHub - moznion/gonstructor: A command-line tool to generate a constructor for the struct. · GitHub
- GitHub - ras0q/gcg: Go Constructor Generator · GitHub
- GitHub - daxartio/constructor: A code generator that generates constructor code for Golang structures. · GitHub
以下の理由により、これらのツールを採用せずに自作することにしました。
- コンストラクタ関数を生成できること
- 自分のユースケース的にはこれさえあれば十分
- メンテナンスされている・あるいはこれからメンテナンスしていく自信があること
- 足りない機能やバグ修正などをすぐにリリースしてもらえると、プロダクト開発に採用しやすい
- 外部コマンドに依存せずに動作すること
- この条件がクリアできれば github.com/moznion/gonstructor をまっすぐ採用していたと思う
ツール名にsimpleとあるように、アグレッシブな機能拡張をする予定はなく、自分にとって必要な最小限のユースケースに絞って実装しています。裏を返すと、自分が欲しいユースケースが出てきたら機能が増える可能性があります。
おわりに
Goのstructのコンストラクタ関数をコード生成するツール gosimplectorgen をリリースしました。コンストラクタ関数を自動生成する、という最小限のユースケースに絞って実装したため、2時間ぐらいでだいたいできたと思います。
ユースケースに合う場合は、どうぞご利用ください。