Go的编译执行流程

Go 语言作为一门静态编译型语言,编译和运行是我们开发过程中经常要用到的功能。下面是编译执行的整体流程:

Go的编译执行流程

1、Go 语言的编译器

Go 语言自带了官方的编译器和链接器,安装 Go 语言环境时就已经包含了编译工具。我们使用的 go build、go run 等命令都会调用 Go 编译器进行工作。

Go 编译器会对源代码进行词法分析、语法分析、类型检查、中间代码生成等处理,最终生成针对特定操作系统和架构的机器代码,也就是我们所说的可执行文件。

编译器还会链接所依赖的内置和外部包,整个编译过程会做大量优化,生成高效的目标代码。这使得 Go 语言可以编译出无依赖、体积小、运行高效的程序。

2、go build 命令编译 Go 程序

Go 语言的编译最基本的就是使用 go build 命令,它会根据指定的参数编译生成一个或多个二进制可执行文件。

go build 的常见用法有:

# 编译main包 
go build 

# 编译某个包
go build packageName

# 同时编译多个包
go build package1 package2

# 指定输出文件名
go build -o outputName

# 指定编译平台和架构
go build -o outputName GOOS=linux GOARCH=amd64

如果指定了输出文件名,则将编译结果保存为该名称;如果没有指定文件名,默认生成的可执行文件名为当前目录名。

3、编译流程输出

编译流程的演示需要go build提供的几个选项协助:这几个选项也适用于go run命令。

$ go help build

...

-n 不执行地打印流程中用到的命令
-x 执行并打印流程中用到的命令,要注意下它与-n选项的区别
-work 打印编译时的临时目录路径,并在结束时保留。默认情况下,编译结束会删除该临时目录。

...

go build流程:

  • 创建临时目录,mkdir -p $WORK/b001/

  • 查找依赖信息,cat >$WORK/b001/importcfg << …

  • 执行源代码编译,/usr/local/go/pkg/tool/darwin_amd64/compile …

  • 收集链接库文件,cat >$WORK/b001/importcfg.link << …

  • 生成可执行文件,/usr/local/go/pkg/tool/darwin_amd64/link -o …

  • 移动可执行文件,mv $WORK/b001/exe/a.out hello

细化成两部分,compile与link,即编译和链接。
go run流程:

与build不同的是在link生成可执行文件后并没有把它移动到当前目录而是通过$WORK/b001/exe/hello执行了程序。

go run能否拿到临时生成的可执行文件?默认是不行的,在go run最后会把临时目录删除。我们可以使用–work保留这个目录:

$ go run -x --work hello.go
WORK=/var/folders/bw/8yw8h4yj2vb6mxtb6t8t41f00000gn/T/go-build149627400

...

$WORK/b001/exe/hello
Hello World

打印了临时目录路径WORK,通过mv命令我们就可以把run生成的hello文件拷贝到当前目录

4、编译生成的文件

Go 语言编译一个 main 包后,会生成一个不依赖其他文件的可执行二进制程序。

如果编译一个普通的包(非 main 包),它不会生成可直接运行的文件,而是产生一个打包了编译结果的.a 文件,供其他主程序链接时使用。

另外,编译测试文件会生成一个包含_test后缀的可执行文件,用于运行测试案例。

所以我们在编译时要区分主程序入口和通用包,以获得不同的编译产物。

5、交叉编译Go程序

交叉编译是指生成目标平台和目标架构的可执行文件,它需要指定平台环境和架构参数,具体的参数有:

  • GOOS:目标平台,如 linux、windows、darwin 等
  • GOARCH:目标处理器架构,如 amd64、386、arm 等

举个例子,想要编译生成 Linux AMD64 平台的可执行文件,可以:

GOOS=linux GOARCH=amd64 go build

通过交叉编译,我们可以在自己的操作系统生成其他平台的程序,然后复制到目标计算机运行,这在持续交付系统中很常用。

6、运行 Go 语言编译生成的程序

Go 语言编译生成的二进制文件可以直接在相应的操作系统平台执行,例如:

./hello // 在Linux/Mac下运行

hello.exe // 在Windows下运行

如果是非 main 包,需要被其他程序引用和链接才会运行。

我们也可以使用 go run 命令直接编译并执行 Go 源码,它比较适合在开发调试阶段使用。

7、分析和解决 Go 语言编译错误

在编译 Go 语言代码的过程中,经常会碰到一些编译错误。

常见的编译错误有:

  • 语法错误:代码格式不正确,不符合语法
  • 导入错误:导入了未安装的包或者导入路径错误
  • 类型错误:类型不匹配或缺少类型转换
  • 标识符未定义:使用了未定义的变量、函数等标识符

针对不同的编译错误,我们需要通过仔细分析来源和修复方法,例如:

  • 检查语法是否正确
  • 导入正确的包 -添加必要的类型转换
  • 定义引用的标识符

只要仔细阅读和理解编译错误提示,就可以针对性地解决问题,再重新编译通过。

8、条件编译

有时候我们会需要根据情况对代码进行有条件地编译,Go 语言通过在编译命令中设置环境标志位来实现条件编译。

常用的条件编译标志包括:

  • GOOS:目标操作系统
  • GOARCH:目标系统架构
  • GCOV:是否开启覆盖率分析

根据这些变量的不同取值,编译器会有选择地编译代码。

我们可以在自动构建系统根据情况设定这些标志,来生成不同平台体系结构的程序。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!