https://mp.weixin.qq.com/s/Rewl0DKnq6CY53m5D3G2qw
希望支持原作者!!!!
我们都知道c的执行包括:预处理---编译---汇编---链接---执行
那么go的一生经历了什么?
from 《码农桃花源》go build时其实包括了(编译和汇编的的过程)
Goland 按照 ASCII 码(实际上是 UTF-8)把这堆二进制位进行了编码
编译过程又包括(词法分析,语法分析,语义分析)
编译前端:
1.词法分析:词法分析将这些我们写的经过编辑器转换后的二进制位进行分析,得到标记(token)序列,.go文件经过扫描器扫描,并进行分割,得到记号,记号一般分为这几类:关键字、标识符、字面量(包含数字、字符串)、特殊符号(如加号、等号)
2.语法分析:上一步生成的 Token 序列,需要经过进一步处理,生成一棵以 表达式为结点的 语法树。此过程可以检测一些形式上的错误
3.语义分析:编译期所能检查的是静态语义,可以认为这是在“代码”阶段,包括变量类型的匹配、转换等。例如,将一个浮点值赋给一个指针变量的时候,明显的类型不匹配,就会报编译错误。而对于运行期间才会出现的错误:不小心除了一个 0 ,语义分析是没办法检测的,在这一阶段检查常量、类型、函数声明以及变量赋值语句的类型,然后检查哈希中键的类型。实现类型检查的函数通常都是几千行的巨型 switch/case 语句
编译后端:
1.中间代码生成:中间代码一般和目标机器以及运行时环境无关,它有几种常见的形式:三地址码、P-代码,这个代码优化其实指的就是(代码里你写的是: t = 1+2,此时优化临时变量t就是3),在生成中间代码之前,会对抽象语法树中节点的一些元素进行替换,如图
如对于 map 的操作 m[i],在这里会被转换成 mapacess 或 mapassign而主程序在执行时会调用 runtime 中的函数,也就是说关键字和内置函数的功能其实是由语言的编译器和运行时共同完成的
2.目标代码生成与优化:不同机器的机器字长、寄存器等等都不一样,意味着在不同机器上跑的机器码是不一样的。最后一步的目的就是要生成能在不同 CPU 架构上运行的代码
链接过程:
编译过程是针对单个文件进行的,单个文件不可避免的会引用其他文件的变量或者函数,这些变量的地址其实是在此阶段才确定。链接就是把一个个目标文件链接成执行文件,最终得到的文件是分成各种段的,比如数据段、代码段、BSS段等等,运行时会被装载到内存中。
go程序启动
main 函数里执行的一些重要的操作包括:新建一个线程执行 sysmon 函数,定期垃圾回收和调度抢占;启动 gc;执行所有的 init 函数等等。
go程序启动命令
go build: 用来编译指定 packages 里的源码文件以及它们的依赖包,编译的时候会到 $GoPath/src/package 路径下寻找源码文件,go build在执行时,会先递归寻找 main.go 所依赖的包,以及依赖的依赖,直至最底层的包
go install:用于编译并安装指定的代码包及它们的依赖包。相比 go build,它只是多了一个“安装编译后的结果文件到指定目录”的步骤。
go run:用于编译并运行命令源码文件。
网友评论