GoSuda

Compile-Time Variable Injection w Go

By wHoIsDReAmer
views ...

Tło

Podczas pracy nad projektem firmowym tym razem sprawdziłem, czy istnieje sposób na wstrzykiwanie zmiennych w czasie kompilacji bez użycia .env. Uważałem, że byłoby to bardzo wygodne, ponieważ wymagałoby tylko jednego pliku, bez .env ani wielu plików konfiguracyjnych.

Po pierwsze, szukałem czegoś w rodzaju CLI go:generate, który generuje pliki stałych na podstawie .env, ale nic takiego nie znalazłem.

Jednak gdyby tak było, mógłbym po prostu modyfikować constants bezpośrednio bez kłopotu generowania ich, i znalazłem metodę wstrzykiwania wartości w czasie kompilacji, podobną do makra include_bytes! w Rust.

Wstrzykiwanie zmiennych w czasie kompilacji

Sposób użycia jest prosty.

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

Zakładając, że istnieje kod jak powyżej, można go wstrzyknąć podczas kompilacji w następujący sposób.

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

Przekazując argumenty za pomocą ldflag, wartość bar jest wstrzykiwana do zmiennej Foo w czasie kompilacji podczas budowania. Jest to proste.

Jeśli w projekcie znajdują się pakiety lub zmienne o tej samej nazwie w wielu miejscach, można określić ścieżkę pakietu.

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

W takich przypadkach można rozróżnić i wstrzyknąć w następujący sposób:

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

Nawet jeśli w tym samym pakiecie znajduje się wiele zmiennych, można po prostu przekazać dodatkowe argumenty.

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

Charakterystyka jest następująca:

  • Zmienna nie musi być publiczna: Zmienne rozpoczynające się małą literą również mogą być wstrzykiwane.
  • Obsługiwany jest tylko typ string: Inne typy nie są obsługiwane.

Referencje