称触发包)。
执行 go build
命令的计算机如果拥有多个逻辑 CPU 核心,那么编译代码包的顺序可能会存在一些不确定性。但是,它一定会满足这样的约束条件:依赖代码包 -> 当前代码包 -> 触发代码包。
顺便推荐一个浏览器插件 Octotree,在看 github 项目的时候,此插件可以在浏览器里直接展示整个项目的文件结构,非常方便:
到这里,你一定会发现,对于 hello-wrold 文件夹下的 pkg 目录好像一直没有涉及到。
其实,pkg 目录下面应该存放的是涉及到的库文件编译后的包,也就是一些 .a
文件。但是 go build 执行过程中,这些 .a
文件放在临时文件夹中,编译完成后会被直接删掉,因此一般不会用到。
前面我们提到过,在 go build 命令里加上 -i
参数会安装这些库文件编译的包,也就是这些 .a
文件会放到 pkg 目录下。
在项目根目录执行 go build -i src/main.go
后,pkg 目录里增加了 util.a 文件:
darwin_amd64
表示的是:
GOOS 和 GOARCH。这两个环境变量不用我们设置,系统默认的。
GOOS 是 Go 所在的操作系统类型,GOARCH 是 Go 所在的计算架构。
Mac 平台上这个目录名就是 darwin_amd64。
生成了 util.a 文件后,再次编译的时候,就不会再重新编译 util.go 文件,加快了编译速度。
同时,在根目录下生成了名称为 main 的可执行文件,这是以 main.go 的文件名命令的。
hello-world 这个项目的代码已经上传到了 github 项目 Go-Questions
,这个项目由问题导入,企图串连 Go 的所有知识点,正在完善,期待你的 star。 地址见参考资料【Go-Questions hello-world项目】。
go install
go install
用于编译并安装指定的代码包及它们的依赖包。相比 go build
,它只是多了一个“安装编译后的结果文件到指定目录”的步骤。
还是使用之前 hello-world 项目的例子,我们先将 pkg 目录删掉,在项目根目录执行:
go install src/main.go
或者
go install util
两者都会在根目录下新建一个 pkg
目录,并且生成一个 util.a
文件。
并且,在执行前者的时候,会在 GOBIN 目录下生成名为 main 的可执行文件。
所以,运行 go install
命令,库源码包对应的 .a
文件会被放置到 pkg
目录下,命令源码包生成的可执行文件会被放到 GOBIN 目录。
go install
在 GoPath 有多个目录的时候,会产生一些问题,具体可以去看郝林老师的 Go 命令教程
,这里不展开了。
go run
go run
用于编译并运行命令源码文件。
在 hello-world 项目的根目录,执行 go run 命令:
go run -x -work src/main.go
-x 可以打印整个过程涉及到的命令,-work 可以看到临时的工作目录:
从上图中可以看到,仍然是先编译,再连接,最后直接执行,并打印出了执行结果。
第一行打印的就是工作目录,最终生成的可执行文件就是放置于此:
main 就是最终生成的可执行文件。
总结
这次的话题太大了,困难重重。从编译原理到 go 启动时的流程,到 go 命令原理,每个话题单独抽出来都可以写很多。
幸好有一些很不错的书和博客文章可以去参考。这篇文章就作为一个引子,你可以跟随参考资料里推荐的一些内容去发散。
参考资料
【《程序员的自我修养》全书】https://book.douban.com/subject/3652388/
【面向信仰编程 编译过程概述】https://draveness.me/golang-compile-intro
【golang runtime 阅读】https://github.com/zboya/golang_runtime_reading
【Go-Questions hello-world项目】https://github.com/qcrao/Go-Questions/tree/master/examples/hello-world
【雨痕大佬的 Go 语言学习笔记】https://github.com/qyuhen/book
【vim 以 16 进制文本】https://www.cnblogs.com/meibenjin/archive/2012/12/06/2806396.html
【Go 编译命令执行过程】https://halfrost.com/go_command/
【Go 命令执行过程】https://github.com/hyper0x/go_command_tutorial
【Go 词法分析】https://ggaaooppeenngg.github.io/zh-CN/2016/04/01/go-lexer-%E8%AF%8D%E6%B3%95%E5%88%86%E6%9E%90/
【曹大博客 golang 与 ast】http://xargin.com/ast/
【Golang 词法解析器,scanner 源码分析】https://blog.csdn.net/zhaoruixiang1111/article/details/89892435
【Gopath Explained】https://flaviocopes.com/go-gopath/
【Understanding the GOPATH】https://www.digitalocean.com/community/tutorials/understanding-the-gopath
【讨论】https://stackoverflow.com/questions/7970390/what-should-be-the-values-of-gopath-and-goroot
【Go 官方 Gopath】https://golang.org/cmd/go/#hdr-GOPATH_environment_variable
【Go package 的探索】https://mp.weixin.qq.com/s/OizVLXfZ6EC1jI-NL7HqeA
【Go 官方 关于 Go 项目的组织结构】https://golang.org/doc/code.html
【Go modules】https://www.melvinvivas.com/go-version-1-11-modules/
【Golang Installation, Setup, GOPATH, and Go Workspace】https://www.callicoder.com/golang-installation-setup-gopath-workspace/
【编译、链接过程链接】https://mikespook.com/2013/11/%E7%BF%BB%E8%AF%91-go-build-%E5%91%BD%E4%BB%A4%E6%98%AF%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%E7%9A%84%EF%BC%9F/
【1.5 编译器由 go 语言完成】https://www.infoq.cn/article/2015/08/go-1-5
【Go 编译过程系列文章】https