Skip to main content

How to conditionally build and test source code

Go allows you to conditionally build source code based on attributes like the Operating System, Architecture, and even just plaintext tags, below is a breakdown of how they work.

File Naming

The easiest way to build for a specific OS/Architecture is to append that information to the end of your filename, some examples include:

  • main_windows.go
  • main_darwin.go
  • main_darwin_arm64.go specific to ARM macs, like MacBook Pros with an M1 processor

The order of these names must be GOOS_GOARCH, the other way around will not work, and of course they still require a name beyond this suffix.

This method is extremely useful if you have some set of functions that only exist in one OS or OS/ARCH combination. If you want something a little more granular, then you will need build tags.

Build tags

Build tags are a special type of comment that go at the top of a code file to instruct the compiler when to conditionally compile the code. They can similarly specify that the code can only be built for a specific platform, but even more powerfully, they can specify multiple platforms. Below is an example of a file specifying that it can be built for Linux or Mac, but not for Windows.

// +build linux darwin

package foo // note the blank line above, that is required

This could also be written similarly below (I realize there are more OSs than Windows/Mac/Linux in reality):

// +build !windows

package foo

The rewritten form says that the file can be compiled for all operating systems that are not Windows.

This can also be used for tests, for example say you want to create a suite of integration tests for your code, you could simply create some test files with a build tag like this:

// +build integration

package foo

During a regular go test command these files will not be executed, however if you run go test --tags integration they will. The caveat is that your regular untagged tests will run in this case as well, in order to get only integration tests to run would be to add a !integration build tag to regular test files.

Sources and useful links