Set Variables In Build

Like many others, there are occasions when and I want to store the value from the environment, like the current build number or Git commit hash, in the source code of a software package so that I can display it on startup or when invoked with a command line switch. This information is only available during the build phase of the application, so something will need to be added to the build process to inject this value once it is known. This is relatively easy to do in C by using the -D switch to the compiler to declare the value as a macro. Even in Java this can be done using Maven resource filtering.

However, I was unaware of how this was done in Go. To date, I have been using a simple form of code generation that involved passing sed over a source file with a dummy string constant. sed would be configured to replace that constant with the version number or Git hash prior to the Go application being built. This worked, but it was a little bit inelegant.

I have since learnt, via this Stack Overflow answer, that it's possible to set the initial value of a Go variable directly from the build command. The process is not as nice as it could be, as it involves actually setting flags to the linker, but it works reasonably well and is much nicer than doing things with sed.

The process is as follows:

First, define a variable that you wish to hold the value you want to get from the environment. The variable must be a string, and either uninitialised or initialised to a string value:

// import path example.com/variable/common
package common

var Version = ""

Then, during the build, use the -X linker option to set the value of the variable to the value you want to get from the environment, like the build number or Git hash. Given this is an option to the linker, this itself needs to be passed in as an argument to -ldflags in the call to go build:

go build -ldflags '-X example.com/variable/common.Version=0.1.1'

This flag can appear multiple times in a single command invocation, and can be used to set a variable in any package.

I've tried this one on a project and it works perfectly. I've yet to back-port it to the other projects where I'm still using sed but I'm hoping to do so soon.

Last updated