Constants, Variables, Build Tags, oh my!

At this point our code is failing to build, which means we’ve met the minimum requirements to prevent our code to be built against a Go version that doesn’t have the behavior we want. But how can we change the code to provide an error to the developer to indicate the Go version isn’t compatible?

The first change we need to make is to include a file that has non-functional versions of the identifiers that we are missing from the first approach. The caveat is that we need to build go19_nobuild.go if the Go version is less than Go 1.9 with // +build !go1.9 :

Of course if we want to accomplish our goal of failing to build, we should never reach the point of the panic statements being evaluated. That said, it’s good to ensure that the code (if compiled) will not work. However, at this point the code no longer fails to build on Go 1.9 because we’ve now created the missing identifiers ( stringForThing and otherStringThing ). The end result would be that the application to panic when first invoking one of these functions, which is not the build failure we were looking for.

To enforce the build failure, we can create a constant ( softwareRequiresGo19 ) that is defined only in the file that will be built if the runtime version is correct. If we make this constant’s name descriptive, and reference it in another file, the build will fail with a semi-descriptive message:

# github.com/theckman/constraint-test/simple2

./simple2.go:16: undefined: softwareRequiresGo19

In comparison to our first approach, this error message is a lot more actionable. It is still a bit confusing with an undefined identifier causing the build failure, but the name of the identifier points us in the direction of what the true problem is.

Now that the problem can be solved with a descriptive error message, can we build a way to have this be done with a single line of code being added to your source code that requires specific Go version runtimes?