1.5 Go语言如何实现跨平台

跨平台是所有编程语言都绕不开的话题,例如,Java一直遵循的“一次编译,到处运行”。Go语言并不支持“一次编译,到处运行”,而是“一次编写,到处运行”。因为Go语言并没有自己的虚拟机,其编译出的可执行文件直接运行在操作系统之上。这在一定程度上牺牲了便利性,但保障了性能。

1.5.1 跨平台的准备工作

针对每种操作系统,Go语言需要编译不同版本的可执行文件,如同我们在前面看到的例子,无论是在macOS还是Windows上,都可以直接编译运行Go程序文件。那么Go语言,更具体地说是go build/run命令,是如何做到的呢?

go build/run命令其实是依赖两个环境变量来识别当前操作系统。我们可以利用go env命令来检查这两个变量的值:

    $ go env GOOS GOARCH
    darwin
    amd64

其中,GOOS代表当前操作系统,GOARCH代表当前CPU架构。当Go安装时,会自动检测操作系统信息,并填充二者的值。因此,即使我们未显式进行任何配置,也可以直接利用go build来编译基于当前操作系统的可执行文件。

表1-1列举了常见的操作系统及GOOS、GOARCH的值。

表1-1 常见的操作系统及GOOS、GOARCH的值

可以利用go tool dist list命令来查看Go语言支持的所有GOOS、GOARCH的可选值,例如:

1.5.2 执行跨平台编译

很明显,Go语言提供了两个环境变量并允许修改,自然是期望能够在单个操作系统上编译出多个目标操作系统的可执行文件。我们尝试在macOS中编译Windows操作系统所需的可执行文件。相应的命令及其输出如下:

在修改GOOS和GOARCH环境变量后执行go build命令,可以看到已经成功编译出了Windows下的可执行文件,并自动追加了exe后缀。

将first.exe复制到Windows系统中,双击或者在CMD中运行该文件,同样可以在控制台打印出字符串“hello Golang”。

相应地,要恢复原来的编译状态,只需要将自定义环境变量GOOS、GOARCH清空即可,例如:

    $ export set GOOS= GOARCH=
    $ echo $GOOS $GOARCH

此时,再次执行编译,将仍然使用go env中定义的默认值进行操作系统和CPU架构的识别。

通过以上描述我们可以看出,Go语言支持的实际是交叉编译(cross compile),通过交叉编译来实现跨平台支持。