Module lessons (5/5)
Build constraints and tags
Build constraints (also called build tags) gate the compilation of a file based on OS, architecture, Go version or custom tags passed on the command line. They are used for cross-platform code, opt-in heavy test files, and similar scenarios.
Modern syntax: //go:build
Since Go 1.17+ the canonical format is the special //go:build comment, placed at the top of the file before package, on a line by itself, followed by a blank line:
//go:build linux
package main
// this file is built ONLY on LinuxThree absolute rules:
- The comment must appear before
package. - It must be followed by a blank line.
- No space between
//andgo:build(it is a syntactic trigger, not just any comment).
Boolean expressions
The expression after //go:build accepts logical operators:
//go:build linux && amd64 // both conditions
//go:build linux || darwin // any one (Unix-like)
//go:build !windows // negation
//go:build (linux || darwin) && !arm64
//go:build go1.22 // Go version ≥ 1.22
//go:build integration // custom tag (see below)The most common built-in tags:
- OS:
linux,darwin,windows,freebsd,js... - Architecture:
amd64,arm64,386,wasm... - Go version:
go1.20,go1.22... (true if the version is ≥). cgo: true if cgo is enabled.
Cross-platform: filename convention
Beyond explicit tags, Go recognises filename suffixes as implicit build constraints:
db_linux.go // linux only
db_windows.go // windows only
db_linux_amd64.go // linux/amd64 only
It is the idiomatic pattern for platform-dependent implementations of the same interface (each file defines the same functions with different code).
Custom tags: opting into heavy tests
Custom tags are any identifier you pass on the command line:
//go:build integration
package mypkg
// tests that need a real DB, run only on demandExecution:
go test -tags=integration ./...Without -tags=integration, the file is invisible to the compiler (the tests inside it do not exist for go test). It is the canonical way to separate unit tests (always) from integration tests (on demand, maybe only in CI).
Old syntax: // +build (deprecated)
Before 1.17 the format was // +build linux (note the space, and that it is +build, not go:build). It is still supported for backward compatibility, but gofmt in Go 1.17+ adds both when it only finds the old one:
//go:build linux
// +build linux
package mainFor new files use only the modern //go:build form.
Exercises
At the top of the file add the build constraint that compiles it ONLY on Linux. Remember the blank line before package.
Show hint
The //go:build comment goes BEFORE package, on a line by itself, followed by a blank line.
Solution available after 3 attempts
Add a build constraint that EXCLUDES Windows (use the negation operator !).
Solution available after 3 attempts
To enable at test time a custom 'integration' tag declared with //go:build integration, which flag do you use?
$ go test -tags=???