Go Linker Flags: Injecting Data at Build Time
Go's -ldflags lets you inject data into your program at build time. This is perfect for embedding version numbers or git commit hashes into variables without hardcoding them. The main footgun is that the target variable must be a top-level string.
Why it exists
Programs often need to know information that isn't available until they are built, like the exact version or the time of compilation. Hardcoding this information is brittle and requires code changes for every release. Linker flags provide a mechanism to pass this data from the build environment directly into the final executable, bypassing the source code.
The mental model
The Go linker (go tool link) is the final step in building your program; it takes all the compiled code and "links" it into a single executable file. The -ldflags option for the go build command is a backdoor to give specific instructions to this linker. Think of it as leaving a note for the construction foreman with last-minute details, like "paint the version number 'v1.2.3' on the front door."
How it works
When you run go build, you can include the -ldflags argument. The Go toolchain passes the string that follows to the linker. The most powerful flag is -X, which sets the value of a string variable. The syntax is -X 'importpath.name=value'. The linker finds the specified variable (name) in the given package (importpath) and replaces its contents with value. The variable in your Go code must be a package-level string, not a local variable inside a function.
When to use it
Use -ldflags to embed build-time metadata into your application. This is essential for versioning (-X main.version=1.2.3), build information (-X 'main.buildDate=(date -u +%FT%TZ)'), or git commit details (-X 'main.commit=(git rev-parse HEAD)'). This makes your binaries self-describing, which is invaluable for debugging and support. You can also use other flags like -s and -w to strip debugging information and the symbol table, creating smaller binaries.
When not to use it
Do not use -ldflags for secrets or configuration that changes between environments. This data is baked into the binary and cannot be changed without recompiling. Use environment variables or configuration files for runtime settings. Also, the -X flag only works for string variables; you cannot inject other data types directly.
One canonical example
In your main.go, declare a package-level variable: var version = "dev". Then, build your program using the command: go build -ldflags="-X 'main.version=v1.0.0'" .. When you run your program and print the version variable, it will now output "v1.0.0" instead of the default "dev". The value was injected by the linker at build time.
Interview question
Which Go variable declaration is correctly configured to have its value injected at build time using the -ldflags -X option?
- a.var MyVersion string = "v1.0.0"Correct
- b.var MyVersion int = 1
- c.const MyVersion string = "v1.0.0"
- d.func main() { var MyVersion string = "v1.0.0" }
Why? this is the answer
The -X flag requires the target variable to be a package-level string variable, making 'var MyVersion string' the correct choice. Constants cannot be modified, and the -X flag only works for string types and package-level variables, not local function variables.
Just read this? Test yourself on what you have been reading.
Read the original → pkg.go.dev
- #go
- #compiler
- #build tools
- #linking
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on go — each one lists the topics its interview covers.
See open roles