Injektion von Variablen zur Kompilierzeit in Go: Verwendung von go build -ldflags -X

Hintergrund
Bei der Arbeit an einem Firmenprojekt habe ich kürzlich untersucht, ob es eine Möglichkeit gibt, Variablen zur Kompilierzeit einzufügen, ohne .env zu verwenden.
Ich dachte, dass dies sehr praktisch wäre, da dann nur eine einzige Datei benötigt wird, ohne .env-Dateien oder mehrere Konfigurationsdateien.
Zunächst suchte ich nach einem go:generate-CLI-Tool, das anhand einer .env-Datei eine Konstantendatei erzeugt, fand aber keines.
Wenn es so ist, könnte man die Konstanten auch einfach direkt bearbeiten, und es wäre nicht nötig, sich mit einem Generierungsschritt zu belasten. Stattdessen fand ich in Rust das Makro include_bytes!, mit dem sich Werte zur Kompilierzeit einfügen lassen.
Injektion von Variablen zur Kompilierzeit
Die Verwendung ist einfach.
1package main
2
3import "fmt"
4
5var Foo string
6
7func main() {
8 fmt.Println(Foo)
9}
Angenommen, es existiert ein Code wie der obige, dann kann man beim Build wie folgt einen Wert injizieren.
1go build -ldflags="-X 'main.Foo=bar'"
Übergibt man das Argument über ldflag, wird der Variable Foo beim Build zur Kompilierzeit der Wert bar zugewiesen. Das ist einfach.
Falls im Projekt Pakete oder Variablen mit demselben Namen an mehreren Stellen existieren, muss man den Paketpfad angeben.
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
In einem solchen Fall kann man die Werte wie folgt getrennt injizieren:
1go build -ldflags="-X 'github.com/myproject/config.Version=v1.0.0' -X 'github.com/myproject/internal/config.BuildTime=2025-05-27'"
Auch wenn mehrere Variablen im selben Paket vorhanden sind, genügt es, zusätzliche Argumente zu übergeben.
1go build -ldflags="-X 'main.Version=v1.0.0' -X 'main.BuildTime=2025-05-27' -X 'main.GitCommit=abc123'"
Die Merkmale sind wie folgt:
- Die Variable muss nicht öffentlich sein: Auch Variablen, die mit einem Kleinbuchstaben beginnen, können injiziert werden.
- Nur der Typ string wird unterstützt: Andere Typen werden nicht unterstützt.