标题: 我最喜欢的 Go 构建选项 [打印本页] 作者: 3AAA 时间: 2022-5-13 16:54 标题: 我最喜欢的 Go 构建选项
这些方便的 Go 构建选项可以帮助你更好地理解 Go 的编译过程。
学习一门新的编程语言最令人欣慰的部分之一,就是最终运行了一个可执行文件,并获得预期的输出。当我开始学习 Go 这门编程语言时,我先是阅读一些示例程序来熟悉语法,然后是尝试写一些小的测试程序。随着时间的推移,这种方法帮助我熟悉了编译和构建程序的过程。
Go 的构建选项提供了更好地控制构建过程的方法。它们还可以提供额外的信息,帮助把这个过程分成更小的部分。在这篇文章中,我将演示我所使用的一些选项。注意:我使用的“构建build”和“编译compile”这两个词是同一个意思。
开始使用 Go
我使用的 Go 版本是 1.16.7。但是,这里给出的命令应该也能在最新的版本上运行。如果你没有安装 Go,你可以从 Go 官网上下载它,并按照说明进行安装。你可以通过打开一个命令提示符,并键入下面的命令来验证你所安装的版本:
$ go version
你应该会得到类似下面这样的输出,具体取决于你安装的版本:
go version go1.16.7 linux/amd64
基本的 Go 程序的编译和执行方法
我将从一个在屏幕上简单打印 “Hello World” 的 Go 程序示例开始,就像下面这样:
$ cat hello.gopackage mainimport "fmt"func main { fmt.Println("Hello World")}
在讨论更高级的选项之前,我将解释如何编译这个 Go 示例程序。我使用了 build命令,后面跟着 Go 程序的源文件名,本例中是hello.go,就像下面这样:
$ go build hello.go
如果一切工作正常,你应该看到在你的当前目录下创建了一个名为 hello的可执行文件。你可以通过使用file命令验证它是 ELF 二进制可执行格式(在 Linux 平台上)。你也可以直接执行它,你会看到它输出 “Hello World”。
$ lshello hello.go$ file ./hello./hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped$ ./helloHello World
Go 提供了一个方便的 run命令,以便你只是想看看程序是否能正常工作,并获得预期的输出,而不想生成一个最终的二进制文件。请记住,即使你在当前目录中没有看到可执行文件,Go 仍然会在某个地方编译并生成可执行文件并运行它,然后把它从系统中删除。我将在本文后面的章节中解释。
$ go run hello.goHello World$ lshello.go
更多细节
上面的命令就像一阵风一样,一下子就运行完了我的程序。然而,如果你想知道 Go 在编译这些程序的过程中做了什么,Go 提供了一个 -x选项,它可以打印出 Go 为产生这个可执行文件所做的一切。
假设你不想编译程序并产生一个实际的二进制文件,但你确实想看到这个过程中的所有步骤。你可以通过使用 -n这个构建选项来做到这一点,该选项会打印出通常的执行步骤,而不会实际创建二进制文件。
$ go build -n hello.go
保存临时目录
很多工作都发生在 /tmp工作目录中,一旦可执行文件被创建和运行,它就会被删除。但是如果你想看看哪些文件是在编译过程中创建的呢?Go 提供了一个-work选项,它可以在编译程序时使用。-work选项除了运行程序外,还打印了工作目录的路径,但它并不会在这之后删除工作目录,所以你可以切换到该目录,检查在编译过程中创建的所有文件。
$ go run -work hello.goWORK=/tmp/go-build3209320645Hello World$ find /tmp/go-build3209320645/tmp/go-build3209320645/tmp/go-build3209320645/b001/tmp/go-build3209320645/b001/importcfg.link/tmp/go-build3209320645/b001/exe/tmp/go-build3209320645/b001/exe/hello$ /tmp/go-build3209320645/b001/exe/helloHello World
其他编译选项
如果说,你想手动编译程序,而不是使用 Go 的 build和run这两个方便的命令,最后得到一个可以直接由你的操作系统(这里指 Linux)运行的可执行文件。那么,你该怎么做呢?这个过程可以分为两部分:编译和链接。你可以使用tool选项来看看它是如何工作的。
首先,使用 tool compile命令产生结果的ar归档文件,它包含了.o中间文件。接下来,对这个hello.o文件执行tool link命令,产生最终的可执行文件,然后你就可以运行它了。
$ go tool compile hello.go$ file hello.ohello.o: current ar archive$ ar t hello.o__.PKGDEF_go_.o$ go tool link -o hello hello.o$ file hellohello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped$ ./helloHello World
如果你想进一步查看基于 hello.o文件产生可执行文件的链接过程,你可以使用-v选项,它会搜索每个 Go 可执行文件中包含的runtime.a文件。
$ go tool link -v -o hello hello.oHEADER = -H5 -T0x401000 -R0x1000searching for runtime.a in /usr/lib/golang/pkg/linux_amd64/runtime.a82052 symbols, 18774 reachable 1 package symbols, 1106 hashed symbols, 77185 non-package symbols, 3760 external symbols81968 liveness data
交叉编译选项
现在我已经解释了 Go 程序的编译过程,接下来,我将演示 Go 如何通过在实际的 build命令之前提供GOOS和GOARCH这两个环境变量,来允许你构建针对不同硬件架构和操作系统的可执行文件。