GoSuda

Compile-Time Variable Injection van Go

By wHoIsDReAmer
views ...

Achtergrond

Tijdens werkzaamheden aan een bedrijfsproject heb ik onlangs onderzocht of er een methode bestaat om variabelen tijdens compile-tijd te injecteren zonder gebruik te maken van .env. Ik veronderstelde dat dit zeer praktisch zou zijn, aangezien slechts één enkel bestand vereist is, in plaats van .env of diverse config-bestanden.

Aanvankelijk zocht ik naar iets dergelijks als een go:generate CLI die een constante bestand genereert op basis van .env, maar dit bleek niet voorhanden te zijn.

Echter, indien dat het geval was, zou men eenvoudigweg constants kunnen aanpassen, en was er geen noodzaak voor het omslachtige proces van gen; bijgevolg vond ik een methode om waarden tijdens compile-tijd te injecteren, vergelijkbaar met de include_bytes! macro in Rust.

Injectie van Variabelen tijdens Compile-tijd

Het gebruik is eenvoudig.

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

Indien men code zoals hierboven heeft, kan deze tijdens de build als volgt worden geïnjecteerd.

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

Wanneer argumenten worden doorgegeven met ldflag, wordt de waarde bar tijdens de compile-tijd bij de build in de variabele Foo geïnjecteerd. Dit is eenvoudig.

Indien er binnen een project packages of variabelen met dezelfde naam op meerdere locaties aanwezig zijn, dient men het package path te specificeren.

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 dergelijke gevallen kan men als volgt injecteren door onderscheid te maken:

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

Zelfs indien er meerdere variabelen in hetzelfde package aanwezig zijn, volstaat het om additionele argumenten door te geven.

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

De kenmerken zijn als volgt:

  • Variabele hoeft niet public te zijn: Variabelen die met een kleine letter beginnen, kunnen eveneens worden geïnjecteerd.
  • Enkel string type ondersteund: Andere types worden niet ondersteund.

Referentie