GoSuda

Compile-Time Variable Injection in Go

By wHoIsDReAmer
views ...

Achtergrond

Tijdens het werken aan een bedrijfsproject heb ik onderzocht of er een methode bestaat om variabelen tijdens compileertijd te injecteren zonder gebruik te maken van een .env-bestand. Ik dacht dat dit zeer handig zou zijn, aangezien men dan slechts één bestand nodig heeft in plaats van een .env of meerdere configuratiebestanden.

Aanvankelijk zocht ik naar een go:generate CLI die een constantenbestand zou genereren op basis van een .env, maar ik kon er geen vinden.

Echter, als dat het geval was, zou het niet nodig zijn om gen te gebruiken; men zou de constanten direct kunnen wijzigen. Vervolgens vond ik een methode, vergelijkbaar met de include_bytes! macro in Rust, om waarden tijdens compileertijd te injecteren.

Variabele-injectie tijdens compileertijd

Het gebruik is eenvoudig.

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

Als er code is zoals hierboven, kan deze tijdens de build als volgt worden geïnjecteerd.

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

Door argumenten via ldflag door te geven, wordt de waarde bar tijdens compileertijd in de variabele Foo geïnjecteerd tijdens het bouwen. Dit is eenvoudig.

Indien er meerdere pakketten of variabelen met dezelfde naam in het project voorkomen, dient het pakketpad expliciet te worden gespecificeerd.

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 de injectie als volgt worden gedifferentieerd:

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

Zelfs als er meerdere variabelen in hetzelfde pakket zijn, hoeft men alleen maar aanvullende 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:

  • Variabelen hoeven niet openbaar te zijn: Variabelen die met een kleine letter beginnen, kunnen ook worden geïnjecteerd.
  • Ondersteuning uitsluitend voor het string-type: Andere typen worden niet ondersteund.

Referentie