首先,自举和cgo是两回事。

自举指的是,go编译器程序是用go语言开发的。编译器代码在go源码的`src/cmd/compile`目录下,可以用`cloc src/cmd/compile`命令看一下 ,基本上都是用go语言写的。

cgo指的是,可以在golang中通过cgo调用c的接口(c++的接口需要用c包装一下)。

然后,说说go的自举。实现自举并不简单。简单地说,需要以下几个步骤:

  1. 先用c写个go1的编译器程序,实现基本的语法特性
  2. 然后用go1写个和第1步一样功能的编译器程序
  3. 用第1步c写的编译器编译第2步go1写的编译器程序,得到go1的编译器,因为这个go1的编程器程序和用c写的编译器功能相同,这样你就得到了一个用go1实现的go1编译器,即它实现了go1自举
  4. 反复以上3个步骤,最终得到go写的go编译器

最后,为什么go要自举?实际上,实现自举的语言并不多。

语言之所以要自举,我认为一个原因是为了验证语言本身,验证语言设计本身是没问题的。因为没有编译器,语言本身就是一堆语法规则而已。能自举说明语言/编译器自身是健壮的。

你可以下载一下go源码,随便改一行代码,用其它版本的go编译后测试一下。

另外,go的编译器是平台相关的,在`src/cmd/compile/internal`可以看到,包含了很多机器码生成相关的包,不同类型的 CPU 分别使用了不同的包生成机器码,其中包括 amd64、arm、arm64、mips、mips64、ppc64、s390x、x86 和 wasm。比如mac编译的二进制不能在centos平台上运行。但是go支持交叉编译,在一个平台上可以编译生成另一个平台的可执行程序。

go的编译过程大致是词法与语法分析 -> 类型检查 -> 中间代码生成 -> 机器码生成。我没有深入看过,准备找时间看一下~

------

我也有个问题,借楼问一下,第一个汇编器怎么来的?