🦍

go generate 入門

2024/06/27に公開

Go で構造体を書く際に Getter を手で書くのは面倒だなと感じました。
普段は Rust で開発していて、derive-getters クレートが便利なので、Go でも同じようなことができないかなと調べたところ go generate で実現できることがわかったので試してみました。

go generate とは

概要

  • Go 1.14 で導入された機能で、コードを自動生成するための仕組み
  • コード内に //go:generate ディレクティブを記述することで、指定されたコマンドを実行し、その出力をコードとして取り込むことが可能

利点

  • コードの冗長性を削減し、可読性を向上させることができる
  • コード生成を自動化することで、開発者の負担を軽減できる
  • テンプレートエンジンやコードジェネレータなどのツールと連携することで、より複雑なコード生成を行うことができる

使い方

  1. コード内に //go:generate ディレクティブを記述(//go:generate の間にはスペースがないことに注意)
  2. ディレクティブに実行したいコマンドとオプションを記述
  3. go genrate コマンドを実行する

go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]

//go:generate stringer -type MyStruct
package main

import "fmt"

type MyStruct struct {
    ID   int
    Name string
    Age  int
}

func main() {
    s := MyStruct{ID: 1, Name: "Taro", Age: 30}
    fmt.Println(s.String()) // 自動生成された String() メソッドが呼び出されます
}

上記の例の場合は、go genrate を実行すると、stringer が実行されr MyStruct 型に String() メソッドが自動生成される。

詳細

  • 生成されたコードには、自動生成されたファイルであることを明記する必要がある
    • ^// Code generated .* DO NOT EDIT\.$

Getters を自動生成してみる

やることは単純で、下記の4ステップです。

  1. フォルダ内の *.go ファイルを見つける
  2. //go:generate getters と記載されている構造体を見つける
  3. getters が付与された構造体のフィールドから Getter レシーバーを作成する
  4. filename_getters.go として出力

go-getters を使ってみる

実際に作ったのがこちら
https://github.com/yusei-wy/go-getters

使い方は

  1. go install github.com/yusei-wy/go-getters@latest でインストール
  2. getters ディレクティブを Getters を生成したい構造体に記述
  3. go-getters コマンド実行

まとめ

以上 go generate を試してみたメモでした。
作っていて思ったのは、これちゃんと go ディレクティブになっているのかなと、正しい使い方ができてるかが心配なのでおかしなところがあれば教えて下さい。

参考資料

Discussion