Golang内部构件,第1部分:主要概念和项目结构

FROM: https://www.altoros.com/blog/...

本系列博客文章供那些已经熟悉Go基础知识并希望对它的内部结构有更深入了解的人使用。 本教程致力于Go源代码的结构以及Go编译器的一些内部细节。 阅读此书后,您应该能够回答以下问题:

Go源代码的结构是什么?
Go编译器如何工作?
Go中节点树的基本结构是什么?

入门

当您开始学习一种新的编程语言时,通常可以找到许多"hello-world"教程,初学者指南和书籍,其中包含有关主要语言概念,语法甚至标准库的详细信息。但是,获取有关诸如语言运行时分配的主要数据结构的布局或调用内置函数时生成的汇编代码之类的信息并不是那么容易。答案显然在源代码中,但是根据我们自己的经验,您可以花大量时间在源代码中徘徊,而无需取得太大的进步。本文的目的是演示如何自行解密Go源码。

在开始之前,我们当然需要我们自己的Go源文件副本。获取它们没有什么特别的。只需执行以下命令。

git clone https://github.com/golang/go

请注意,main分支中的代码正在不断更改,因此我们在此博客文章中使用release-branch.go1.4分支。

了解项目结构

如果查看Go存储库的/ src文件夹,则可以看到很多文件夹。 其中大多数包含标准Go库的源文件。 标准命名约定始终在此处应用,因此每个程序包都在一个文件夹内,其名称与该程序包名称直接对应。 除了标准库外,还有很多其他的东西。 我们认为,最重要和最有用的文件夹在下表中列出。

文件夹 描述
/src/cmd/ 包含不同的命令行工具。
/src/cmd/go/ 包含Go工具的源文件,该工具下载并构建Go源文件并安装软件包。在执行此操作时,它将收集所有源文件并调用Go链接器和Go编译器命令行工具。
/src/cmd/dist/ 包含一个负责构建所有其他命令行工具和标准库中所有软件包的工具。您可能需要分析其源代码,以了解在每个特定工具或程序包中使用了哪些库。
/src/cmd/gc/ 这是Go编译器与体系结构无关的部分。
/src/cmd/ld/Go 链接器的与体系结构无关的部分。与体系结构相关的部分位于带有“ l”后缀的文件夹中,该后缀使用与编译器相同的命名约定。
/src/cmd/5a/,6a,8a和9a 在这里,您可以找到适用于不同体系结构的Go汇编程序编译器。 Go汇编程序是一种汇编语言,不能精确地映射到基础计算机的汇编程序。取而代之的是,每种架构都有一个独特的编译器,可以将Go汇编程序转换为机器的汇编程序。您可以在官方文档中找到更多详细信息。
/src/lib9/,/src/libbio,/ src /liblink 在编译器,链接器和运行时包内使用的不同库。
/src/runtime/ 间接包含在所有程序中的最重要的Go软件包。它包含整个运行时功能,例如内存管理,垃圾回收,goroutines创建等。

在Go编译器内部

如上所述,Go编译器的与体系结构无关的部分位于/src/cmd/gc/文件夹中。入口点位于lex.c文件中。除了一些常见的东西(例如解析命令行参数)之外,编译器还执行以下操作:

  • 初始化一些常见的数据结构。
  • 遍历所有提供的Go文件,并为每个文件调用yyparse方法。这导致实际的解析发生。 Go编译器使用Bison作为解析器生成器。该语言的语法在go.y文件中有完整描述(我将在稍后提供更多详细信息)。结果,此步骤生成一个完整的分析树,其中每个节点代表已编译程序的一个元素。
  • 递归地迭代生成的树几次,并进行一些修改,例如,为应隐式键入的节点定义类型信息,将某些语言元素(如类型转换)重写为对运行时包中某些函数的调用,并执行其他一些工作。
  • 解析树完成后执行实际的编译。节点被翻译成汇编代码。
  • 创建包含已生成的汇编代码和其他一些数据结构(例如,符号表)的目标文件,该文件已生成并写入磁盘。

Diving into the Go grammar

Understanding nodes

你可能感兴趣的:(golang)