Go 语言的构建约束

go Feb 06, 2019
Golang 语言作为21世纪出现的少数语言之一,它有吸收并继承了上世纪发明的那些语言的优点。

build constraints (构建约束)就是其中不错的设计。有了这些设计, 我们可以在源码中通过注释的方式指定编译选项,比如只允许在 Linux 下, 或者在 386 的平台上编译之类的情况; 还可以通过文件名来约束构建, 比如 *_linux.go, 就是只允许在Linux 下编译, *_windows_amd64.go 就是只允许在 windows 和 amd64 下进行编译。

构建约束可以在很多文件中进行使用, 不单单适用 .go 文件。但是必须要注意的是, 通过注释实施构建约束的话, 必须要放在文件的开头, 要优先于空行和其它注释(包含包注释和协议注释)之前。也就是说必须在 package 语句的前面写。

因为 Go 的 godoc 是可以提取代码中的注释然后转换为文档的, 在 package 语句之前写的注释会被认为是包级别的注释。而构建约束又得在所有注释之前, 那么为了区分包级别的注释, 官方给出的方法是: To distinguish build constraints from package documentation, a series of build constraints must be followed by a blank line.
要在构建约束与包级别的注释之间添加空行进行区分。

通过注释实施的构建约束还可以进行逻辑表达, 即 and, or 之类的语义。Go 官方定义的是:
A build constraint is evaluated as the OR of space-separated options. Each option evaluates as the AND of its comma-separated terms. Each term consists of letters, digits, underscores, and dots. A term may be negated with a preceding !.
如果构建约束中有空格, 那么就是 or 关系; 如果是逗号分隔, 那么就是 and 关系; ! 表示 not。例如:

// +build linux,386 darwin,!cgo

就是表示 (linux and 386) or (darwin and (not cgo))

而且 Go 还支持多行的构建约束, 多行之间是 and 关系, 例如:

// +build linux darwin
// +build 386

就是表示 (linux or darwin) and 386

Go 官方还定义了常用的一些约束:

  • 限制目标操作系统, 也就是要和 runtime.GOOS 一致
  • 限制目标架构平台, 也就是要和 runtime.GOARCH 一致
  • GC 或者 GCCGO 等编译器支持的约束
  • cgo 约束, 也就是说如果支持 cgo 的话, 就可以参与编译
  • 限制 go 版本, go1.1 表示从 go1.1 开始向前兼容; go1.2 表示从 go1.2 开始向前兼容;...
  • 自定义的约束

如果你想临时让某个文件不参与编译, 可以添加注释约束: // +build ignore.

Go 官方定义里还表示可以自定义约束, 那么这个可以这么使用呢? 了解 Go 的人都知道 Go 内置了 testing 库和单元测试框架, 跑跑一般的单元测试还是可以, 但是如果要做一些简单的集成测试就会出现很多麻烦了, 因为 go test 命令默认就是跑最基本的单元测试。那么这么只执行集成测试的代码呢? 其实这就可以借助自定义约束来实施。例如我们可以在需要进行集成测试的 .go 文件头加上 // +build integration 注释, 然后运行 go test -tags="integration" 就可以只运行我们的集成测试代码了。

虽然可以通过注释的方式对构建进行了约束, 但是文件名的构建约束反而显得更不错, 至上在工程文件目录里看着一目了然。文件名前缀只要含有 _GOOS, _GOARCH, _GOOS_GOARCH 的就可以。例如 xxx_linux.go, yyy_windows_amd64.go, zzz_386.go 等等。



相关资料链接:

Go official doc#Build Constraints
Binary Only Packages
Using Go’s build constraint tag to help build mock services for service testing
Golang | cmd - go build 构建约束

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.