一起了解Go语言编译链接的过程

2023年 8月 7日 35.6k 0

1: 前言

interface、channel的文章中经常会提到,Go在编译时会将interface和channel关键字转换成runtime中的结构和函数调用。所以我觉得很有必要就Go的编译过程理一理做个进行总结,然后结合之前对底层原理总结的文章,那么对整个逻辑会更加清晰。我也是查了各种资料,尽量把整个过程能总起出一些东西来,学习嘛,总是需要不断总结,分享!

1.1 什么是ASCII字符

ASCII 代表美国信息交换标准代码,用于电子通信。在计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。 上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定,这被称为 ASCII 码,一直沿用至今。

它使用整数对数字(0-9)、大写字母(AZ)、小写字母(az)和分号(;)、感叹号(!)等符号进行编码。整数比字母或字母更容易存储在电子设备中符号。例如,97用于表示“a”,33用于表示“!” 并且可以很容易地存储在内存中。

我们知道Go是采用UTF-8是编码规则, 和ASCII码之间的联系呢?了解UTF-8之前我们先了解Unicode,因为ASCII码只能表示英语,不能表示其他语言。Unicode 为世界上所有字符都分配了一个唯一的数字编号,但是Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

因为互联网的普及,UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。Unicode的编码规则,对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码,因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。

对于ASCII码、Unicode、UTF-8之间的联系就不展开更多更细的总结,用个栗子来说明下我们编写的Go程序文件和编码之间关系。

1.2 图说ASCII码和Go程序文件

这里参考下一个网络上的图片说明,首先我们Go代码Hello.go如下

package main
 
import "fmt"
 
func main() {
 fmt.Println("hello world")
}

我们知道我们用心敲下的每一行代码都是字节序列,然后每个字节代表一个字符,代码和ASCII码之间的对应关系就是中间一列代表文本对应的 ASCII 字符,最右边的列就是我们的代码,跟下面的对照表示一一对应的,比如hello.go文件的首字母p的值是对应的就是70。

16进制查看文件内容

ASCII码对照表

hello.go 文件都是由 ASCII 字符表示的,它被称为文本文件,8个bit看成一个单位,假定源程序都是ASCII码,转换为我们人类都能更好理解的go程序,那么到这里编码和程序文件之间的关系已经清楚了,接下来就从编译和链接过程来看有哪些步骤,然后每一个步骤做了什么!

2:编译过程

我们知道Go 程序并不能直接运行,每条 Go 语句必须转化为一系列的低级机器语言指令,将这些指令打包到一起,并以二进制磁盘文件的形式存储起来,也就是可执行目标文件。这个过程就涉及到对源文件进行词法分析、语法分析、语义分析、优化,最后生成汇编代码文件(以.s作为文件后缀),再经过汇编器将汇编文件生成.o二进制程序,最后经过链接器转换成可执行的目标程序(比如windows下的.exe程序)。

源文件编译为执行程序的过程

编译过程

2.1 词法分析

词法分析(lexical analysis)维基百科上给出的定义:是计算机科学中将字符序列转换为标记(token)序列的过程。进行词法分析的程序或者函数叫作词法分析器(lexical analyzer,简称lexer),也叫扫描器(scanner)。词法分析器一般以函数的形式存在,供语法分析器调。

Go在编译源码时首先,由词法分析器(lexer)对源代码文件进行解析,将文件中的字符串序列转为Token序列(在src/cmd/compile/internal/syntax/tokens.go),token包含标识符、关键字、特殊符号等都是以常量的形式存在。

const (
_ token = iota
_EOF // EOF

// names and literals
_Name // name
_Literal // literal

// operators and operations
// _Operator is excluding '*' (_Star)
_Operator // op
_AssignOp // op=
_IncOp // opop
_Assign // =
_Define // :=
_Arrow //

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论