Conditional compilation with build tags
suggest changeBuild tags allow for limited conditional compilation i.e. compiling different versions of code based on some criteria.
Tags are specified per file, at the top of the file, followed by an empty line and the code.
A typical use case for tags is to provide to implementation of the same functionality and pick the one that is compiled with tags.
For example, if you have 3 files in the directory:
foo_alt.go
// +build alt
package main
func foo() {
fmt.Printf("This is alternative foo\n")
}
foo.go
// You can have other comments before build tags
// +build !alt
package main
func foo() {
fmt.Printf("This is regular foo\n")
}
main.go
package main
func main() {
foo()
}
Compiling without any build tags:
> go build -o main .
> ./main
This is non-alt foo
Compiling with alt
build tag:
> go build -tags alt -o main_alt .
> ./main_alt
This is alternative foo
When we specified -tags alt
, we compiled foo_alt.go
file, because it contains // +build alt
directive which tells the build tool to compile the file if build tag alt
is provided with -tags
option.
We didn't compile foo.go
file because it contains // build !alt
directive which tells the build to not compile the if build alt
is provided.
Similarly, if we didn't specify any build tags for go build
command, file foo.go
was compiled (because it only says to not compile if alt
tag is provided) and foo_alt.go
was not compiled.
Argument -tags
applies to many commands e..g. go run
, go install
, go test
etc.
Specifying multiple tags
You can specify multiple build constraints (tags):
// +build tag1,tag2 tag3,!tag4
// +build tag5
package foo
This encodes a condition (tag1
AND
tag2)
OR
(tag3
AND
(
NOT
tag4)) AND tag5
.
Similarly, for the go
command: go build -tags "tag1 tag2"
.
Ignoring files (excluding from compilation)
// +build ignore
package foo
Predefined build tags
Go toolchain uses several build tags:
arm
,arm64
,386
,amd64
,s390x
: for different processor architectureswindows
,darwin
,linux
,dragonfly
,freebsd
,netbsd
,openbsd
,plan9
,solaris
,android
: for operating systemscgo
: when cgo is enabledgc
orgccgo
: for gc and gccgo toolchainsgo1.11
for Go version 1.11+,go1.12
for Go version 1.12+ etc.
Using file name in place of a build tag
An alternative to providing build tag directive in the file is using a file name suffix e.g. foo_windows.go
is equivalent of including // +build windows
in the file.
Pitfalls
The following doesn't work as expected:
// +build alt
package main
func foo() {
fmt.Printf("This is alternative foo\n")
}
You need an empty line after build tag line:
// +build alt
package main