

Setting Go variables from the outside - FiloSottile
https://blog.cloudflare.com/setting-go-variables-at-compile-time/

======
travjones
The CloudFlare blog is awesome. This post was succinct, but super valuable to
teams who need to manage versioning, etc. (really there are tons of use
cases). I like how they admitted that they were doing things inefficiently and
explained what they learned to make their dev lives easier. Thanks again,
CloudFlare!

------
zalmoxes
I just learned about this two days ago and used it for the first time to set
the version in an CLI app.

In my main app I set var Version = "unreleased" and the build scripts sets the
correct version.

[https://github.com/groob/CommPhone/blob/master/release.sh#L1...](https://github.com/groob/CommPhone/blob/master/release.sh#L15)

~~~
fizzbatter
I used to use ldflags heavily for things like that, but nowa days i tend to
avoid them - depending on the use case atleast.

Why? Well, many of my projects i don't want to distribute a binary for. I
don't want to have to make a whole build process where i build multiple OSs,
host it (github upload, etc), and update corresponding documents.

`npm install -g foo` doesn't require that, `go install foo` doesn't require
that, so why am i putting myself through a large headache over nothing?

So these days, if i'm writing a Go binary that i intend to mostly use myself,
or have other Go developers use, i bake the version/etc information _into_ the
files via a build script. For those projects, the Go source is a 100%
complete, valid binary. ldflags are still awesome for certain things, but it
is really, really nice when your source code is a proper representation of the
output result.

Anyway, not bashing ldflags, just talking about my experience :)

~~~
zalmoxes
As a sysadmin who's embraced Go for a lot of my day to day work, it really
bugs me when Go developers do not publish binary releases of their apps.

1) Go makes this easy. 2) One of the advantages of Go is that the program is
compiled. Most of the people who want to use your app are not going to be
other go developers. 3) Versioning your code is a good practice and if there's
a hosted binary release somewhere I can rely on it in my docker/config
management process.

~~~
hamax
Maybe there is a market for "go get" in the cloud where you could paste a
repository link and get back binaries for a selected distribution. It should
be pretty easy to set up too.

~~~
SEJeff
I can see it now:

Hmmmmm, why are these downloading from bastion.nsa.gov?

------
bbrazil
We've been doing this in our makefiles and exposing it to the user
[https://github.com/prometheus/prometheus/blob/0e383b0b9f4ff0...](https://github.com/prometheus/prometheus/blob/0e383b0b9f4ff029789f130964a4f18184200418/Makefile.INCLUDE#L71)

Cloudflare have been putting out quite a few high-quality posts recently.

------
andmarios
Nice and clean solution. I usually write the version string of a program with
a git pre-commit hook.

Like this:

    
    
        HASH="$(git rev-parse --short HEAD)"
        sed 's/Version = .*/Version = "'"$HASH"'+"/' -i version.go
        git add version.go

------
andrewstuart2
This is one area that the Go ecosystem leaves me wanting a bit more. Idiomatic
Go says that my package should be go-gettable, which AFAIK just uses `go
install` command after fetching dependencies.

Is there an idiomatic way to include build options/tasks, while remaining go-
gettable?

~~~
ominous_prime
This doesn't affect `go get`. You can use the same options when fetching the
package, setting the variable or leaving it as the default.

    
    
         go get -ldflags="-X main.Who CloudFlare" import/path/package

~~~
andrewstuart2
I guess that's pretty reasonable. Especially coupled with sensible defaults
for your variables like "unreleased" in the article. If you're building for a
release you're probably a lot more up-to-speed on the needs for a release
build anyway.

------
mononcqc
What's the advantage of doing that vs. just using a macro defined at compile-
time?

------
mathrawka
In my build scripts, I like to have this added, so I can see what commit was
used in building the binary:

    
    
        go build -ldflags "-X main.versionId `git rev-parse HEAD`"

~~~
FiloSottile

        git describe --tags --always --dirty="-dev"
    

This will give you just the tag name if the current commit is tagged (useful
for version tags), otherwise TAG-N-COMMIT, where N is the number of commits
since TAG, and finally append -dev if the tree is dirty.

~~~
McElroy
Almost what I've been doing but I didn't know about the "dirty" option so I
had a script I wrote to check if there are uncommitted changes and append a
suffix like you do. Now I can get rid of that. Thanks.

