1. 前言
编译是将高级语言编写的源代码转换成机器能够执行的指令的过程。
编译可以分为几个阶段,这包括词法分析、语法分析、语义分析、中间代码生成、优化和目标代码生成。
对于Go语言(Golang)来说,编译不仅仅是构建程序的一部分,而且是其设计哲学的核心,确保了速度、安全性和跨平台的灵活性。
参考文档:
2. Go编译器的特点
- 快速编译:Go编译器以其极快的编译速度而闻名。这得益于Go的简洁语法、依赖管理系统和编译器的设计。快速的编译对提高开发效率和迭代速度至关重要。
- 静态链接:Go编程语言创建的二进制文件是静态链接的,这意味着所有依赖库都被包含在最终的可执行文件中。因此,我们可以在没有Go环境的系统上运行它们,无需担心依赖问题。
- 跨平台编译:使用Go,我们可以轻松地为不同的操作系统和架构编译程序。通过设置GOOS和GOARCH环境变量,Go编译器可以产生针对几乎任何平台的编译输出。
- 内存安全:Go的编译器会在编译时进行内存安全的检查,例如自动内存管理(GC)。这一机制有效防止了像野指针或内存泄漏这样的问题。
- 报错和警告:Go编译器非常严格,对于一些可能在运行时引起问题的代码段,如未使用的变量或导入的包,将无法通过编译,直到这些问题被修复。
3. 编译命令
3.1. 标准编译命令
编译Go代码非常简单,使用go build
命令即可。在大多数情况下,这一命令无需任何参数,它会自动处理所有文件依赖和包引用。
1 | go build |
此命令将编译当前目录中的Go源文件。如果当前目录是包含Go代码的单个包的目录,它将产生一个可执行文件。
go build 需要的是一个路径,让编译器可以找到哪些需要编译的go文件。当省略所有参数时,就意味着使用当前目录进行编译。
下面的几条命令是等价的:
1 | go build |
3.2. 自定义输出
使用-o
标志,我们可以为生成的二进制文件指定一个名字及路径。
1 | go build -o myapp |
3.3. 交叉编译
Go语言(Golang)支持交叉编译,即在一个平台上编译生成另一个平台可执行的程序。
这意味着我们可以在Mac上为Linux系统编译二进制文件,也可以在Windows上为ARM处理器编译程序,等等。
Go语言交叉编译非常容易实现,因此被广泛应用于生成各种不同系统和架构的可执行程序,使得开发者可以轻松为多个平台构建应用。
要构建特定平台的应用程序,我们可以设置GOOS
和GOARCH
环境变量,分别表示操作系统和处理器架构。
常见的GOOS值有:
darwin
(Apple MacOS)linux
windows
freebsd
常见的GOARCH值有:
amd64
(64位x86架构)386
(32位x86架构)arm
(ARM架构)arm64
(64位ARM架构)
例如,我们可以为Windows 64位系统生成可执行文件,即便我们正在使用Linux或macOS。
1 | GOOS=windows GOARCH=amd64 go build |
这将在我们的非Windows系统上生成一个Windows可执行程序。
交叉编译注意事项:
1、安装golang依赖
确保在进行交叉编译之前所有项目依赖都已经正确安装,运行go mod tidy
可以帮助我们清理和同步项目依赖。此外,我们的项目代码也应该没有平台相关的依赖,否则可能需要根据目标平台进行适配。
2、安装目标平台的库和工具链
交叉编译时,可能需要注意目标平台的特定库或工具链支持。
例如,当我们在64位系统上编译32位程序时,相应32位的库应该是可用的。还有,某些依赖C语言库(如CGO程序)的Go程序可能需要额外配置或安装相应的跨平台C语言库和工具链。
3、目标平台测试
建议在目标平台上测试编译结果,以确保程序的正常运行。
4. 简单编译示例
4.1. 编译Linux二进制文件
1 | GOOS=linux GOARCH=amd64 go build -o myapp myapp.go |
生成一个Linux下可运行的可执行文件myapp
。
注意:如果是在Windows中执行编译,需要使用set
命令配置环境变量:
1 | C:\> set GOOS=linux |
4.2. 编译Windows二进制文件
1 | GOOS=windows GOARCH=amd64 go build -o myapp.exe myapp.go |
生成一个名为myapp.exe
的Windows可执行文件。
4.3. 编译Mac二进制文件
1 | GOOS=darwin GOARCH=amd64 go build -o myapp myapp.go |
生成一个Mac系统可运行的二进制文件myapp
。
4.4. 编译ARM二进制文件
1 | GOOS=linux GOARCH=arm GOARM=7 go build -o myapp myapp.go |
这个命令指定了GOARM
环境变量,它用于定义ARM的具体版本。
比如,GOARM=7
通常用于诸如Raspberry Pi 2/3这样的较新ARM设备上。
5. 复杂编译示例
1 | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -ldflags="-w -s" -o /go/bin/pod-data-retorer |
编译命令释义:
1、 CGO_ENABLED=0
:
CGO_ENABLED
环境变量控制是否启用CGo。CGo允许Go代码调用C代码。- 设置为
0
表示禁用CGo,这有助于确保生成的可执行文件能在没有C库(特别是在别的平台上没有C环境的情况下)的环境中运行。
2、 GOOS=linux
和 GOARCH=amd64
:
- 这两个变量定义了目标编译平台的操作系统和处理器架构。
GOOS=linux
指定目标操作系统是Linux。GOARCH=amd64
指定目标处理器架构是64位x86架构。
3、go build -a -installsuffix cgo
:
go build
是Go语言的标准编译命令。-a
选项告诉Go编译器重建所有涉及到的东西,包括所有的包(即使它们没有变化)。-installsuffix cgo
是用来给输出的文件名添加一个后缀,以区分不同编译配置下的编译结果。由于我们设置了CGO_ENABLED=0
,所以这里使用的后缀是cgo
。
4、-ldflags="-w -s"
:
ldflags
表示链接器(linker)标志。-w
和-s
是链接选项,分别用于减小生成的二进制文件大小:
--w
告诉编译器忽略DWARF调试信息,从而减小了生成文件的大小。
--s
用于去除符号表和调试信息,进一步减小二进制文件的大小。
5、-o /go/bin/pod-data-retorer
:
-o
选项用来指定输出的二进制文件名。/go/bin/pod-data-retorer
是输出的二进制文件的完整路径和名称。这里指定了文件会被放在/go/bin/
目录下,并且命名为pod-data-retorer
。
综上所述,这条命令会生成一个静态链接的、没有C库依赖、文件尺寸优化的Linux 64位平台的可执行文件pod-data-retorer
,并且会放在/go/bin
目录下。轻量化和去除C库依赖的特点使得生成的可执行文件特别适合在容器化环境(如Docker)中运行,因为它能够减少容器镜像的大小,并且降低对环境的依赖。