However a colleague suggested injecting the version string into the binary itself at compile time so I decided to investigate this novel approach.
go tool link specifies that the -X argument allows us to define arbitrary string values
go tool link
...
-X definition
add string value definition of the form importpath.name=value
...
go build help explains that there is an 'ldflags' option which allows the user to specify a flag list passed through to go tool link
go build help
...
-ldflags 'flag list'
arguments to pass on each go tool link invocation.
...
So we can pass a string definition through the go command (build, run etc)!
In the above program we can see that we define a variable foo in package main.
Thus the fully qualified name of this variable is main.foo, thus this is the name we pass.
$ go run main.go
injected var is []
$ go run -ldflags '-s -X main.foo=bar' main.go
injected var is [bar]
This can be used in novel ways to inject the output of external commands at compile time such as the build date.
$ go run -ldflags "-X 'main.foo=$(date -u '+%Y-%m-%d %H:%M:%S')'" main.go
injected var is [2017-09-13 13:44:59]
This is a nice feature that I'm sure has applications beyond my reckoning at this time. In my use case it makes for a compact, neat solution, however it does cause some indirection when reading the code making it harder to follow so I would argue should be used sparingly. It has the nice quality of being immutable over env vars which could potentially be rewritten. Anyhow it is a pretty cool linker feature!
No comments:
Post a Comment