Modify Variables In Go Binaries During Build | by Percy Bolmér | Mar, 2022

You’ll be able to set the variable worth throughout the construct, resembling model quantity, shopper IDs with the Construct command.

Picture by Percy Bolmér. Gopher by Takuya Ueda, Authentic Go Gopher by Renée French (CC BY 3.0)

Have you ever ever used hardcoded model numbers, or tried passing configurations to a binary that states the model of the software program?

I’ve, and it really works, however it is vitally error-prone. It’s simple to overlook to alter that configuration and many others or keep the model throughout a number of merge requests.

I lastly discovered an incredible resolution, we will modify variables contained in the binaries throughout the construct time by including construct flags. This permits us to arrange the CI/CD to cross the git commit as a model and many others, or have completely different releases specify the runner ID primarily based on the deployment.

Utilizing this method makes it simpler to take care of and management the particular values since we will simply place them contained in the CI/CD. We are able to do that by leveraging the Linker flags.

Linker & Ldflags

The go construct device permits us to cross choices to the Linker, which is the part answerable for assembling the binary.

We are able to cross choices to the Linker by utilizing the --ldflags flag to the construct device. There are very many choices you’ll be able to cross, however on this article, we’ll concentrate on solely considered one of them. --ldflags accepts a string of configurations, so the enter will probably be enclosed by "".

You’ll be able to view all of the choices by working the construct with the --help choice.

go construct --ldflags="--help"
All of the linker choices accessible to make use of within the construct device

The choice we’re all in favour of utilizing is the -X choice. That is the definition from the assistance print.

-X definition        add string worth definition of the shape importpath.identify=worth

As you’ll be able to see, we will use the -X flag and goal the variable we need to modify by utilizing the import path (the trail you employ to import a package deal) and utilizing .variableName to focus on a sure variable utilizing its identify, after which the worth we would like.

Allow us to do that out with a easy instance undertaking.

-X, Setting The Variable Worth

Start by creating a brand new undertaking, I take advantage of the module identify That is vital to notice as a result of it’ll later be used as an import path.

mkdir buildflags
go mod init
contact foremost.go

We’ll fill the foremost.go with a easy perform that prints the model and shopper identify.

foremost.go — The straightforward program that prints the variabel values.

You’ll be able to attempt viewing the output by constructing and working this system.

go construct -o foremost && ./foremost
// Outputs
2022/03/08 19:23:28 Beginning runner client-1.0.0 model 0.0.1

Allow us to attempt rebuilding the binary, however this time we’ll use the --ldflags and apply the -X command to set the runner into client-2.0.0. The package deal we work in is foremost in order that would be the import path.

go construct -o foremost --ldflags="-X 'foremost.runner=client-2.0.0'"

Strive working this system once more, and examine the output change the runner identify.

// Outputs
2022/03/08 19:27:21 Beginning runner client-2.0.0 model 0.0.1

You’ll be able to modify a number of flags, all it is advisable to do is add a brand new -X flag contained in the command.

go construct -o foremost --ldflags="-X 'foremost.runner=client-2.0.0' -X 'foremost.model=0.0.2'"

You must attempt working the binary, no shock, the model can be modified.

Even higher, you may as well goal sub-packages if you wish to. To do that, create a subfolder named model, and add a file named model.go which accommodates the Model variable as a substitute of foremost.go.

model/model.go — The subpackage that we are going to be modifying

Be sure we replace the foremost.go to make use of the superb new model package deal.

I don’t really advocate you having a model package deal, however you get the thought

foremost.go — The principle package deal that now makes use of the construct package deal.

Now we will attempt to rebuild the binary, and ensure to replace the model quantity utilizing the -X flag. This time, you’ll be able to cross the complete import path, which is the module identify.

go construct -o foremost --ldflags="-X '' -X 'foremost.runner=client-1.0.1'"

Upon working that binary, you need to see the values change.

Including Git Commit Tag As Model

One cool factor is that now once we can modify values throughout the construct, you’ll be able to automate model dealing with by utilizing the git commit, and many others.

Within the folder of the undertaking, we’ll init a git repository and commit the present recordsdata so we will get a commit hash.

git init
git add .
git commit -m "check"

To print a brief commit hash, you should utilize the next git command.

git rev-parse --short HEAD

We are able to merely inject that into the -X flag, and set the worth of that output.

go construct -o foremost --ldflags="-X '$(git rev-parse --short HEAD)' -X 'foremost.runner=client-1.0.1'"

Working this system with this binary for me now prints the next end result

2022/03/08 20:54:35 Beginning runner client-1.0.1 model f525917


The instance we use could be very easy, however you are able to do many issues with this. I’ve seen variations being injected, characteristic flags, and extra. One simple resolution for characteristic flags that ought to differ between shoppers could be passing a real worth for the enabled features. That is most likely the simplest characteristic flag resolution to make use of, no want for frameworks to handle it.

The perfect place to have these flags is within the CI/CD in keeping with me, to regulate completely different releases, variations, and shopper ids.

I hope you discovered this attention-grabbing, I discovered it very helpful once I discovered this.

Are you utilizing ldflags already, if that’s the case, for what? And what are the use circumstances you’ll be able to consider? I might love to listen to from you concerning your ideas about these flags.

More Posts