GoSuda

Go 的 Compile-Time Variable Injection

By wHoIsDReAmer
views ...

背景

本次在进行公司项目工作时,我尝试寻找一种无需 .env 即可在 컴파일 타임 时注入 변수 的方法。我认为这样做会非常 편리,因为无需 .env 或多个 콘피그 文件,只需单个文件即可。

起初我尝试寻找基于 .env 生成 상수 文件的 go:generate CLI 之类的工具,但没有找到。

然而,如果那样的话,直接修改 constants 即可,无需麻烦地进行 gen;我找到了一个类似于 러스트 中的 include_bytes! 매크로,可以在 컴파일 타임 时注入 값 的方法。

컴파일 타임 변수 주입

使用方法很简单。

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 타입: 不支持其他 타입

참조