go 编译约束//go:build dev //+build
前言
在真实环境中,我们可能需要为不同的编译环境编写不同的 Go 代码,所以需要做构建约束。
比如:syscall.NewLazyDLL("test.dll")
加载 dll
的程序在 Linux
平台中就没有,所以当你写程序时就需要指定包含这个 API 的文件只能在 Windows
下面编译,在其他平台自动忽略,这样就不会代码移植到别的平台出现编译时错误了。
Go 语言对这一问题的解决方案是在文件层面进行有条件的编译:每个文件要么在编译中,要么不在。
也就是,假设不符合构建约束的场景。那么会直接不编译这个文件,因为它不在编译范围内。
那程序再想运行时,就会报错,表示找不到文件。
构建约束的背景
最早的构建约束是在 2011 年 9 月引入的,我们平时常见的构建约束(build constraint),也叫做构建标记(build tag),构建约束必须出现在 package 之前。
通过代码文件中添加注释进行约束
平时会在 Go 工程的文件中的最开始会看到如下行注解:
// +build
为了将构建约束与包文档区分开来,构建约束后必须跟一个空行。
// +build linux,386 darwin,!cgo
又或是:
// +build linux darwin
// +build amd64
还可以根据 Go 版本来约束:
// +build go1.9
其主要支持如下几种:
- 指定编译的操作系统,例如:windows、linux 等,对应 runtime.GOOS 的值。
- 指定编译的计算机架构,例如:amd64、386,对应 runtime.GOARCH 的值。
- 指定使用的编译器,例如:gccgo、gc,是否开启CGO,cgo。
- 指定 Go 版本,例如:go1.19、go1.20 等。
- 指定自定义的标签,例如:编译时通过指定 -tags 传入的值。
- // +build ignore,编译时自动忽略该文件
- ……
标签之间有如下几种运算关系:
空格表示:AND
逗号表示:OR
!表示:NOT
换行表示:AND
比如:
// +build linux,386 darwin,!cgo
运算表达式为:(linux && 386) || (darwin && !cgo)
使用文件后缀进行约束
这种方式就是通过文件的后缀名来对要指定平台的编译的文件进行约束,文件格式如下:
sourcefilename_GOOS_GOARCH
上面的格式就是文件名_系统名_架构名.go,GOOS和GOARCH可以通过go env看到,也可以在环境变量中指定;下面举个例子:
user_windows_amd64.go //在 windows 中 amd64 架构下才会编译,其他的环境中会自动忽略
user_linux_arm.go // 在 linux 中的 arm 架构下才会编译,其他环境中会自动忽略