Injekce proměnných v době kompilace v Go: použití go build -ldflags -X

Pozadí
Při práci na firemním projektu jsem hledal způsob, jak vkládat proměnné v době kompilace bez použití .env souboru.
Myslel jsem si, že by to bylo velmi pohodlné, protože by stačil jediný soubor, bez .env nebo několika konfiguračních souborů.
Nejprve jsem hledal nástroj typu CLI pro go:generate, který by na základě .env vygeneroval soubor s konstantami, ale žádný jsem nenašel.
Pokud je to tak, pak by stačilo jednoduše upravit constants a nebylo by nutné zbytečně spouštět generování. Zároveň jsem našel možnost, jak vkládat hodnoty v době kompilace, podobnou makru include_bytes! v Rustu.
Vkládání proměnných v době kompilace
Použití je jednoduché.
1package main
2
3import "fmt"
4
5var Foo string
6
7func main() {
8 fmt.Println(Foo)
9}
Pokud máme výše uvedený kód, lze při sestavení hodnotu vložit následujícím způsobem.
1go build -ldflags="-X 'main.Foo=bar'"
Předáním argumentu přes ldflag se při sestavení v době kompilace do proměnné Foo vloží hodnota bar. Je to jednoduché.
Pokud se ve svém projektu nachází proměnné nebo balíčky se stejným názvem na více místech, stačí uvést cestu k balíčku.
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
V takovém případě lze hodnoty rozlišit a vložit takto:
1go build -ldflags="-X 'github.com/myproject/config.Version=v1.0.0' -X 'github.com/myproject/internal/config.BuildTime=2025-05-27'"
Pokud je více proměnných ve stejném balíčku, stačí jednoduše předat další argumenty.
1go build -ldflags="-X 'main.Version=v1.0.0' -X 'main.BuildTime=2025-05-27' -X 'main.GitCommit=abc123'"
Vlastnosti jsou následující:
- Proměnná nemusí být veřejná: lze vložit i hodnotu do proměnné začínající malým písmenem
- Podporován je pouze typ string: jiné typy nejsou podporovány