GoSuda

Compile-Time Variable Injection i Go

By wHoIsDReAmer
views ...

Bakgrunn

Mens jeg arbeidet med et selskapsprosjekt denne gangen, undersøkte jeg om det fantes en metode for å injisere variabler ved kompileringstid uten bruk av .env. Jeg antok at dette ville være svært fordelaktig, ettersom det kun ville kreve en enkelt fil i stedet for .env eller multiple konfigurasjonsfiler.

Initialt søkte jeg etter noe tilsvarende en go:generate CLI som kunne generere en konstantfil basert på .env, men fant ingen slik løsning.

Imidlertid, hvis det var tilfellet, kunne man like gjerne modifisere constants direkte, og det var unødvendig med en omstendelig gen-prosess; følgelig søkte jeg etter en metode for å injisere verdier ved kompileringstid, analogt med include_bytes! makro i Rust.

Injeksjon av variabler ved kompileringstid

Bruken er enkel.

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

Gitt at man har kode tilsvarende den ovennevnte, kan injeksjonen utføres som følger ved bygging.

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

Ved å overføre argumenter via ldflag, injiseres verdien 'bar' i variabelen 'Foo' ved kompileringstid under bygging. Dette er enkelt.

Dersom det finnes pakker eller variabler med samme navn på flere steder i et prosjekt, kan dette håndteres ved å spesifisere pakkestien.

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

I slike tilfeller kan injeksjonen separeres og utføres som følger:

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

Selv når det finnes multiple variabler innenfor samme pakke, er det tilstrekkelig å overføre ytterligere argumenter.

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

Karakteristikkene er som følger:

  • Variabelen behøver ikke være public: Variabler som starter med små bokstaver kan også injiseres.
  • Kun string-type støttes: Andre typer støttes ikke.

Referanse