Compile-Time Variable Injection w Go
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.