Setting Compile-time Strings in Go
It is handy to have a program be able to tell you its own version number. But it's a pain to maintain version strings manually. So why not let Go do it for you? It turns out to be pretty easy to do. When reading the code for Drone.io I ran across this cool trick for setting string values at compile time.
Here's a basic Go program that prints the version string and exits:
package main
import "fmt"
var version string
func main() {
fmt.Printf("Version: %s\n", version)
}
Unsurprisingly, if we run this program, we get the following output:
$ go run showversion.go
Version:
Ideally, version info should be set at build time, when we know exactly what the version number should be. Go provides a way to do this in the form of the -X
flag to the linker. This flag allows you to set a string variable to a specific value during the linking stage. But we don't usually invoke the linker directly when working with Go. So to pass the linker any options, we have to use the -ldflags
flag on go build
.
Say we want to override version
in our main
package above. We can do that with go build
like this:
$ go build -ldflags "-x main.version 1.0.0" showversion.go
The above tells the linker to set the main.version
variable to 1.0.0
. Now if we run the resulting show version
program, we get the following output:
$ ./showversion
Version: 1.0.0
We could get even fancier and have Git generate the version number for us, based on the tag and the SHA:
$ git tag 1.0.1
$ go build -ldflags "-x main.version $(git describe --tags)" showversion.go
$ ./showversion
Version: 1.0.1
And check out what happens when we make the next commit:
$ git commit -am "One more change after the tags"
$ go build -ldflags "-x main.version $(git describe --tags)" showversion.go
Version: 1.0.1-1-g7e60d6f
This is a great way to let tools do the maintenance work.