//go:build go1.17 || (linux && 386) || (darwin && !cgo)
构建约束(build constraint)也叫做构建标记(build tag),以文件名或注释形式,标记当前文件是否参与构建过程。
文件名形式的构建约束比较简单,暂且按下不表。Go 中一直存在一种 // +build
形式的构建约束语法,标记间的组合关系通过空格、逗号或多行来表示,例如:
// +build go1.17 linux,386 darwin,!cgo
这种语法示意性非常差!哪怕是下面这种多行形式,示意性也并没有得到多少改善。
// +build go1.17
// +build linux,386
// +build darwin,!cgo
而 go1.17 引入的新语法示意性就非常棒了。上面的约束用新语法表示成:
//go:build go1.17 || (linux && 386) || (darwin && !cgo)
新的约束语法可以理解为,标签表达式为真,当前文件参与构建。
文件名按照以下模式构成构建约束:
*_GOOS
*_GOARCH
*_GOOS_GOARCH
例如 source_windows_amd64.go 只会在 windows 操作系统中 amd64 架构下参与构建。
想要知道 GOOS 与 GOARCH 所有可选项,可通过 go tool dist list
查看。
使用要点:
.go
、.s
等;// +build xxx
可以有多行,新版约束 //go:build xxx
只能有一行;//
与 go
之间不能有空格。构建标记 xxx
,可用以下几种类型的备选词:
-tags
传递的值;标记之间的组合关系用 ||
、&&
、!
、(
、)
表示。
纵览众多开源项目,重多构建约束注释中 //go:build xxx
你或许遇到过许多奇奇怪怪的标记 xxx
,那些陌生的标记往往是自定义 tag 。例如:依赖注入工具 wire 的 wire.go 文件有 //go:build wireinject
这条约束。wireinject
便是 wire 这个工具自己定义的 tag 。在构建过程中会带到构建指令中 go build -tags wireinject
。
下面举个例子,应用自定义 tag:
app/main.go
|
|
app/pro.go
|
|
构建 app
go build -tags pro
输出结果:
./app
> Free Feature #1
> Free Feature #2
> Pro Feature #1
> Pro Feature #2
app 这款应用中我们自己定义了一个名为 pro 的构建标签,当我们需要给 app 增加 pro 版本的功能时,无需修改代码,通过在构建时加 -tags pro
即可完成。