跨平台代码

典型“动态语言思维”的错误

if runtime.GOOS == "windows" { return nil }
......

该方式仅在编译完成后执行时进行操作系统的判断,但在编译时如果代码中引用了该平台不支持的调用,会导致无法编译。

条件编译

Go使用构建标签(build tags)和代码文件的命名约定来支持Go软件包的条件编译

构建标签

构建标签必须在代码文件里位于package声明的上方,并且后跟一个空行。

构建标签遵循以下三个原则:

  1. 空格隔开的选项是或(OR)的关系
  2. 逗号隔开的选项是与(AND)的关系
  3. 每个选项由字母和数字组成。如果前面加上!,则表示反义

如下例子表示该文件将在linux/386darwin/386平台才会被编译,用逻辑表达式表示就是:(linux OR darwin) AND 386

// +build linux darwin
// +build 386

文件名后缀

通过源码文件的文件名实现,如果文件名包含_$GOOS.go后缀,那么这个源码文件只会在对应的平台被编译。其他平台会忽略这个文件。另一种约定是_$GOARCH.go。这两种后缀可以组合起来,但要保证顺序,正确的格式是_$GOOS_$GOARCH.go,错误的格式是_$GOARCH_$GOOS.go

mypkg_freebsd_arm.go // 只在 freebsd/arm 系统编译
mypkg_plan9.go       // 只在 plan9 编译
mypkg_darwin.go      // 只在macos 系统编译

如何选择

通常来说,当只有一个特定平台或体系需要指定时,我们选择文件名后缀的方式,相反,如果文件需要指定给多个平台或体系架构使用,或者需要排除某个特定平台时,选择构建标签的方式

mypkg_linux.go         // 只在 linux 系统编译
mypkg_windows_amd64.go // 只在 windows amd 64位 平台编译
// 在所有类unix平台编译
// +build darwin dragonfly freebsd linux netbsd openbsd
 
// 在非Windows平台编译
// +build !windows

执行交叉编译

在编译时给go build命令设置OSARCH参数

CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go

参考链接:https://juejin.cn/post/6874561730149384200 作者:kevinyan