mainパッケージに変数を埋め込みたいとき
Goで作ったアプリで --version
用にバージョン番号とビルド日時を埋め込みたい。
そんな時、-ldflags
を使えばいいのはwell-knownだと思います。
go build -ldflags=" -X main.compiled 'ビルド日時' -X main.version 'バージョン番号' " .
サブパッケージに変数を埋め込みたいとき
では main
以外に変数を埋め込む時は、どうすればよいのでしょうか?
ui/backend/workerの3つのサーバーからなるシステムを作っているとします。
3つのmain
パッケージがopts
(コマンドラインパーサ)パッケージを共有しています。
バージョン番号はui/backend/workerで同じ番号を使いたいので、opts
に埋め込みたいと思います(3つのmain
それぞれではなく)。
この場合は、main.version
ではなく opts
内のVersion
を書き換えなくてはなりません。
- $GOPATH/src/github.com/my-team/app/ - cmd/ - ui/ # UIサーバー用の main パッケージ - backend/ # backendサーバー用の main パッケージ - worker/ # SQSワーカー用の main パッケージ - libs # 共通のライブラリ群 - dynamodb/ - pgsql/ - s3/ - opts/ # コマンドラインパーサー、ここに共通のVersionを埋め込みたい
// cmd/ui/ui.go package main import ( "http" "github.com/my-team/app/libs/opts" ) func main() { o := opts.Parse() # 共通のコマンドラインパーサー ... }
// libs/opts/opts.go package opts import ( "flag" "os" "fmt" ) var ( // この2つをビルド時に書き換えたい Version string // 共通のバージョン番号 Compiled string // 共通のビルド日時 ) func Parse() Options{ v := flag.BoolVar('version', false, "print version number") ... flag.Parse() if *v { fmt.Printf("version: %s, build: %s", Version, Compiled) os.Exit(0) } }
解決
なんのことはない、main
をパッケージのパスに変えれば良いのです。
go build -ldflags=" -X github.com/my-team/app/libs/opts.Compiled 'ビルド日時' -X github.com/my-team/app/libs/opts.Version 'バージョン番号' " .
"go tool"の1つ"nm"で、実行ファイルの中でどんな変数が使われているのかが見られます。
$ go tool nm bin/ui bin/ui: 4010d0 T main.init bin/ui: b1fc4f D main.initdone. bin/ui: 400c00 T main.main bin/ui: b0b890 D github.com/my-team/app/libs/opts.Compiled bin/ui: b1b4e0 D github.com/my-team/app/libs/opts.Version