Until recently, I didn’t really think about how to get an application’s version into its binary without some horrendous use of sed or manually changing hardcoded values. Normally my application’s version is just the Docker image tag, but how do I get the version info into the actually binary? Digging through the internet I found a super easy way to have the linker do it with ldflags.

Just create a global variable where your main function lives:

package main

import "fmt"

var (
	Version string
)

func main() {
	fmt.Printf("Version: %s\n", Version)
}

And set the flag when you build your application:

go build -ldflags="-X main.Version=1.0.0"

Where main is the package that your variable Version lives. Now when we put it all together we can see the version that was passed in:

$ go build -ldflags="-X main.Version=1.0.0"
$ ./main
Version: 1.0.0

You can take this a step further by setting more details in a Makefile dynamically using info from git. Same idea in the source file:

package main

import "fmt"

var (
	Version string
	Commit  string
)

func main() {
	fmt.Printf("Version: %s Commit: %s\n", Version, Commit)
}

Assuming your project is in a git repo, create the Makefile:

LD_FLAGS := -X main.Commit=$(shell git rev-parse HEAD) -X main.Version=$(shell git describe --always)

build:
    go build -ldflags="$(LD_FLAGS)"

Build using the Makefile and run:

$ make build
$ ./main
Version: some-git-version Commit: some-git-commit

And now you can have version information in all your Go applications.