GoSuda

Инжектиране на променливи по време на компилация в Go

By wHoIsDReAmer
views ...

배경

В хода на работата по проект на компанията, проучих дали съществува метод за инжектиране на променливи по време на компилация без използване на .env файл. Смятах, че това би било изключително удобно, тъй като би изисквало само един файл вместо .env или множество конфигурационни файлове.

Първоначално търсих CLI инструмент като go:generate, който да генерира константен файл на базата на .env, но такъв не беше открит.

Въпреки това, ако трябваше просто да модифицирам константите, нямаше нужда от сложна генерация, и така открих метод за инжектиране на стойности по време на компилация, подобно на include_bytes! макроса в Rust.

컴파일 타임 변수 주입

Начинът на употреба е елементарен.

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

Ако приемем, че съществува горепосоченият код, инжектирането може да се извърши по следния начин по време на компилация:

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

При подаване на аргументи чрез ldflag, стойността bar се инжектира в променливата Foo по време на компилация. Това е просто.

В случай че в проекта съществуват няколко пакета или променливи с едно и също име, е необходимо да се уточни пътят до пакета.

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

В такива случаи инжектирането може да се разграничи по следния начин:

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

Дори когато в един и същ пакет има множество променливи, е достатъчно просто да се подадат допълнителни аргументи.

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

Характеристиките са следните:

  • Променливата не е задължително да бъде public: Могат да се инжектират и променливи, започващи с малка буква.
  • Поддържа само string тип: Други типове не се поддържат.

참조