Go 提供了按条件编译某文件的能力,通过在 Go 文件中加入一行特殊的注释来实现:
//go:build (darwin && cgo) || linux
// +build darwin,cgo linux
packaget getIP
func main() {
// ...
}其中这两行 build 注释是等价的:
//go:build是 Go 1.17 及以后的语法。只能存在一行//+build是 Go 1.16 及之前的语法。可以存在多行,多行间的关系是 AND。1.17 及以上的 gofmt 遇到这种老语法时,会自动生成新的语法
你可以看到里面用了这些变量 darwin, cgo 等。可用的变量来源于:
- GOOS 的值,比如
linux,darwin,windows等 - GOARCH 的值,比如
386,amd64,arm等 - Go 编译器,
gc或gccgo cgo,如果CGO_ENABLED被设置成 1- Go 版本号,如
go1.1表示 Go 1.1 版本及以上,go1.12表示 Go 1.12 版本及以上 - 其他在
go build -tags中指定的 tag
另外,如果你的 go 文件名,除去扩展名和 _test 后缀后,满足这些 pattern:
*_GOOS,比如a_windows.goa_windows_test.go*_GOARCH,比如a_arm.gomath_386.s*_GOOS_GOARCH,比如a_linux_arm.go
表示隐式的 build constraints。
使用 -tags 的例子
google/wire 使用了 -tags 的能力。
在编写 wire.go 时你需要指定 wireinject
//go:build wireinject
// +build wireinject使用 wire CLI,它会通过 -tags 机制,扫描目录下的带 wireinject 的文件,并生成 wire_gen.go,其中带有这样的头:
//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject这使得 go 在正常编译此项目时,会跳过 wire.go 而仅使用 wire_gen.go。
参考
Build constraints 注释的语法在 Go 1.17 版本后有变化:
JetBrains 也有一个 文档 描述此功能。