例如,https://github.com/golang/sys/blob/master/cpu/cpu_gccgo_x86.go#L5 :
//go:build (386 || amd64 || amd64p32) && gccgo
// +build 386 amd64 amd64p32
// +build gccgo
package cpu
在我看来,作为构建标记,// +build ...
可以很好地工作。
为什么仍然明确指定 //go:build
?
顺便说一句,很难找到//go:build
的手册,但是// +build
很容易(https://pkg.go.dev/cmd/go#hdr-Build_constraints)
答案 0 :(得分:9)
//go:build
是 Go 1.17(将于明年 8 月发布)中引入的新条件编译指令。
它旨在替换 // +build
指令,因为新语法带来了一些关键改进:
//go:generate
//go:build foo && bar
,而旧的 // +build
注释的语法不太直观。例如 AND 用逗号 // +build foo,bar
表示,OR 用空格 // +build foo bar
go fmt
支持,它会自动修复指令在源文件中的错误位置,从而避免 common mistakes 在指令和包语句之间不留空行。这两个构建指令将在几个 Go 版本中共存,以确保平滑过渡,如相关提案文档中的 outlined(低于 N = 17,强调我的) :
<块引用>Go 1.N 将开始转换。在 Go 1.N 中:
构建将开始首选 //go:build
行进行文件选择。如果文件中没有 //go:build
,则任何 // +build
行仍然适用。
如果 Go 文件包含 //go:build
而没有 // +build
,构建将不再失败。
如果 Go 或程序集文件在文件中包含 //go:build
太晚,构建将失败。 Gofmt 将移动错位 //go:build
和 // +build 行到它们在文件中的正确位置。
Gofmt
将使用与其他 Go 布尔表达式相同的规则(所有 //go:build
和 &&
运算符周围的空格)格式化 ||
行中的表达式。
如果一个文件只包含 // +build
行,gofmt
会在它们上面添加一个等效的 //go:build
行。
如果文件同时包含 //go:build
和 // +build
行,gofmt
会认为 //go:build
是事实来源并更新// +build
行匹配,保留与早期版本的 Go 的兼容性。 Gofmt
也会拒绝 //go:build
被认为太复杂而无法转换为 // +build
格式的行,尽管这种情况很少见。 (请注意此项目符号开头的“If”。Gofmt
不会向只有 // +build
的文件添加 //go:build
行。)
buildtags
中的 go vet
检查将添加对 //go:build
约束的支持。 当 Go 源文件包含具有不同含义的 //go:build
和 // +build
行时,它会失败。如果检查失败,可以运行gofmt -w
。
当 Go 源文件包含 buildtags
而没有 //go:build
并且其包含的模块具有列出 Go 1.N 之前的版本的 go 行时,// +build
检查也会失败。如果检查失败,可以添加任何 // +build
行,然后运行 gofmt -w
,它将用正确的行替换它。或者可以将 go.mod
go 版本升级到 Go 1.N。