GoSuda

Go コンパイル時変数の注入: go build -ldflags -X の活用法

By wHoIsDReAmer views ...

背景

今回の会社プロジェクトの作業において、.env なしでコンパイル時に変数を注入する方法がないかを調べてみました。この方法であれば .env や複数の設定ファイルがなく、単一のファイルだけで済むため、非常に便利だろうと考えました。

まず最初に探したのは、.env をもとに定数ファイルを生成する go:generate の CLI のようなものでしたが、見つかりませんでした。

ただ、そうするのであれば単に constants を修正すればよく、わざわざ gen を実行する必要はありませんでした。そこで、Rust の include_bytes! マクロのように、コンパイル時に値を注入できる方法を調べました。

コンパイル時変数の注入

使い方は簡単です。

1package main
2
3import "fmt"
4
5var Foo string
6
7func main() {
8    fmt.Println(Foo)
9}

上記のようなコードがある場合、ビルド時に次のように注入できます。

1go build -ldflags="-X 'main.Foo=bar'"

ldflag で引数を渡すと、ビルド時のコンパイル時に Foo 変数へ bar の値が注入されます。シンプルです。

もしプロジェクト内に同じ名前のパッケージや変数が複数の場所に存在する場合は、パッケージパスを明示すればよいです。

1// github.com/myproject/config/config.go
2package config
3
4var Version string
5
6// github.com/myproject/internal/config/config.go
7package config
8
9var BuildTime string

このような場合は、次のように区別して注入することができます:

1go build -ldflags="-X 'github.com/myproject/config.Version=v1.0.0' -X 'github.com/myproject/internal/config.BuildTime=2025-05-27'"

同じパッケージに複数の変数がある場合も、追加の引数を渡すだけで済みます。

1go build -ldflags="-X 'main.Version=v1.0.0' -X 'main.BuildTime=2025-05-27' -X 'main.GitCommit=abc123'"

特徴は次のとおりです:

  • 変数が public でなくてもよい: 小文字で始まる変数にも注入可能です
  • string 型のみサポート: それ以外の型はサポートされていません

参照