Golang 编译器分析
概述
CPU 是计算机执行指令的单元,每种架构的 CPU 都有自己的指令集,例如常见的 x86 , ARM 等,由此构成的编程语言称为机器语言,由机器语言构成的程序是 CPU 唯一能够执行的程序,机器语言是面向机器的低级编程语言。 而在软件开发中,人的生产效率是第一需要考虑的因素,除此之外,我们还需要更多、更强的抽象能力与表达能力(例如并发、模块化、作用域等),来编写结构更加复杂的程序;像 Java, Golang 这类编程语言是面向人类的高级编程语言。 因此,从高级语言到机器语言的转换是执行任何程序的先行步骤,这个过程叫着编译,完成该过程的程序叫着编译器。编译是个复杂的过程,通常被划分为如下几个阶段:
词法分析 –> 语法分析 –> 语义分析 –> 中间代码生成 –> 机器无关代码优化 –> 目标代码生成 –> 目标代码优化
编译器是一个非常庞大复杂的系统,更准确地说,这其实是一个完整的领域。通常而言,程序语言设计者会采用已有的编译器工具链来构造不同的模块,例如使用 Lex 来构造词法分析器,使用 Yacc 来构造语法分析器,然后配合自己实现的其他模块来组装成一个完整的编译器,这样的话技术栈将非常宽泛,深入学习该语言的编译过程就变成了一件非常困难的事情。通常情况下,编程语言的编译器都会使用另一种语言来实现,这对用户学习其编译过程也是极度不友好的。因此除非是编译器的实现者,对于大多数普通程序员而言,对编译器的知识通常只是停留在理论阶段,而无法与所使用的语言直接关联起来。对于自己所使用语言的编译过程知识的缺失,是造成无法深入了解、掌握甚至精通该语言的障碍之一。
Golang 在1.5以前编译器的大多数工作都是通过 C 语言编写的,1.5 以后实现了自举,即 Go 语言的整个编译器(Compiler)及运行环境(Runtime)都是用 Go 语言写成的,包括其词法分析器、语法分析器都是完整的 Go 语言程序。这给想要深入学习 Go 语言的用户提供了非常友好的支持,对于 Go 语言的任何特性,从语法规则到类型系统,我们都可以深入到编译器中去寻找实现原理,甚至可以自己动手给语言增加新的功能,例如箭头函数、内置函数等,即使无法在生产环境使用,这种实践也是非常有趣的。