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 enabledgcorgccgo: for gc and gccgo toolchainsgo1.11for Go version 1.11+,go1.12for 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