Compile-Time Variable Injection in Go
Background
While working on a company project recently, I investigated whether there is a method to inject variables at compile time without using .env
.
I considered this approach to be exceedingly convenient, as it would require only a single file instead of .env
or multiple configuration files.
Initially, I searched for a go:generate
CLI tool or similar that could generate a constants file based on .env
, but none was found.
However, if that were the case, one could simply modify the constants directly without the cumbersome process of generation, and I subsequently discovered a method for injecting values at compile time, akin to Rust's include_bytes!
macro.
Compile-Time Variable Injection
The usage is straightforward.
1package main
2
3import "fmt"
4
5var Foo string
6
7func main() {
8 fmt.Println(Foo)
9}
Assuming code such as the above exists, injection can be performed during the build process as follows.
1go build -ldflags="-X 'main.Foo=bar'"
By passing arguments via ldflag, the value bar
is injected into the variable Foo
at compile time during the build. It is simple.
If packages or variables with the same name exist in multiple locations within the project, one should specify the package path.
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
In such cases, injection can be performed with distinction as follows:
1go build -ldflags="-X 'github.com/myproject/config.Version=v1.0.0' -X 'github.com/myproject/internal/config.BuildTime=2025-05-27'"
Even when multiple variables reside within the same package, one can simply provide additional arguments.
1go build -ldflags="-X 'main.Version=v1.0.0' -X 'main.BuildTime=2025-05-27' -X 'main.GitCommit=abc123'"
The characteristics are as follows:
- Variables need not be public: Variables starting with a lowercase letter can also be injected.
- Only string type is supported: Other types are not supported.