GoSuda

Compile-Time Variable Injection v jazyce Go

By wHoIsDReAmer
views ...

Pozadí

Při práci na firemním projektu jsem zkoumal, zda existuje metoda pro vkládání proměnných v době kompilace bez použití souborů .env. Domníval jsem se, že by to bylo mimořádně pohodlné, neboť by to vyžadovalo pouze jediný soubor namísto .env či mnoha konfiguračních souborů.

Nejprve jsem hledal něco jako go:generate CLI, které by na základě .env generovalo soubory konstant, avšak nic takového jsem nenalezl.

Nicméně v takovém případě by postačovala přímá úprava konstant, a nebylo by nutné se zatěžovat generováním; namísto toho jsem nalezl metodu pro vkládání hodnot v době kompilace, podobně jako makro include_bytes! v Rustu.

Vkládání proměnných v době kompilace

Použití je jednoduché.

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

Pokud předpokládáme kód jako výše, v době sestavení lze vkládat proměnné následujícím způsobem.

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

Předáte-li argumenty pomocí ldflag, hodnota 'bar' bude vložena do proměnné Foo v době kompilace během sestavování. Je to jednoduché.

Pokud se v projektu na více místech vyskytují balíčky nebo proměnné stejného názvu, postačí specifikovat cestu k balíčku.

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

V takových případech lze vkládat s rozlišením následovně:

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

I v případě, že se v jednom balíčku nachází více proměnných, postačí předat další argumenty.

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

Vlastnosti jsou následující:

  • Proměnná nemusí být public: Lze vkládat i proměnné začínající malým písmenem.
  • Podporován je pouze typ string: Jiné typy nejsou podporovány.

Odkazy