How do you inject a version string at build time with -ldflags? What does this program print?
Question 429HardGo 1.22 to 1.25
package main
import "fmt"
const commit = "none"
var version = "dev"
var built = defaultBuilt()
func defaultBuilt() string { return "unknown" }
func main() { fmt.Println(version, commit, built) }
// go build -ldflags "-X main.version=1.4.0 -X main.commit=abc123 -X main.built=2025-01-01" .
Prints: 1.4.0 none unknown.
versionworks.-X importpath.name=valuesets a package-level string variable that is uninitialized or initialized to a constant expression.commitis a constant, which gets inlined at compile time.-Xis silently ignored.builtis initialized by a function call, which runs at init time and overwrites the linker value. Again there is no error.
Other points:
- The symbol needs the full import path, for example
-X github.com/acme/app/internal/buildinfo.Version=.... Onlymainuses the short form. - A typo is silently ignored.
-s -wstrips the symbol table and DWARF debug info.- Since Go 1.18 you often don't need
-Xfor the commit:debug.ReadBuildInfo()exposesvcs.revision,vcs.timeandvcs.modifiedautomatically.
What interviewers want: "string vars only, no consts or computed initializers, full import path, failures are silent."
More on Modules, Packages & Tooling
- Q427What are the cgo pointer-passing rules, and how does runtime.Pinner help?
- Q428How do you cross-compile Go and produce a fully static binary for a scratch container?
- Q430What build metadata does a Go binary carry, and how do you make builds reproducible?
- Q431What does go vet catch? What does it report for the code below?
- Q432How do staticcheck and golangci-lint differ from go vet? How would you set up linting for a team?
- Q433How does //go:embed work? Show the three target types.