ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Go语言的编译和运行过程

Go语言的编译和运行过程 Go语言的编译和运行过程Go语言的编译步骤前端编译后端编译示意图Go语言的运行步骤程序启动运行代码的初始化 全局变量-init函数执行主逻辑执行程序退出main函数执行结束和资源清理回收示意图Go语言的编译步骤前端编译前端编译主要负责词法分析、语法分析、语义检查和生成中间代码输入是 Go 源代码输出是 IRIntermediate Representation中间表示。词法分析将源代码字符拆分成为Token词法单元语法分析根据Go语言的语法规则将Token序列转化成为抽象语法树(AST)。表示代码的语法结构比如函数定义、表达式嵌套。类型检查语义检查遍历抽象语法树验证代码语义的合法性。中间代码生成将代类型信息的AST转化为SSAStatic Single Assignment静态单赋值形式的 IR。SSA 特点每个变量仅被赋值一次便于编译器进行优化如常量折叠、死代码消除。示例x : 1 2 会被优化为 x : 3常量折叠。后端编译后端编译将 IR 转换为目标平台的机器码主要包括优化、代码生成和链接。中间代码优化对于SSA形式的IR进行一系列优化。提升最终的二进制文件的性能。常量传播将常量直接替换到使用处如 a 5; b a 3 → b 8死代码消除移除永远不会执行的代码如 if false { … } 中的内容函数内联将小型函数的代码直接嵌入调用处减少函数调用开销循环优化如循环展开、循环不变量外提等。机器码生成将优化后的中间代码IR转化成为对应平台的汇编代码再进一步转化成为机器码二进制指令链接将多个编译单元.o目标文件和依赖的标准库合并成为一个可执行文件。示意图源代码.go→ 词法分析 → Token 序列→ 语法分析 → AST抽象语法树→ 类型检查 → 带类型的 AST→ 中间代码生成 → SSA 形式的 IR→ 中间代码优化 → 优化后的 IR→ 机器码生成 → 目标文件.o→ 链接 → 可执行二进制文件Go语言的运行步骤指的是go程序的编译好的二进制文件从加载到内存并执行的全过程。涉及程序启动初始化主逻辑执行资源清理等阶段程序启动当用户执行编译好的二进制文件时操作系统会先完成加载程序到内存中的相关工作随后进行程序初始化阶段。操作系统加载操作系统通过系统调用将程序加载到内存中解析可执行文件头设置程序的代码段指令数据段全局变量。建立进程上下文栈空间、寄存器状态将程序入口点设置为初始化执行地址。Go运行初始化启动线程创建操作系统创建第一个线程通常称m0,初始机器线程执行Go运行时的启动代码。内存分配器初始化初始化堆内存管理结构。为后续的分配内存做准备。Goroutine调度器初始化初始化调度器核心组件G结构体、M结构体、P结构体运行代码的初始化 全局变量-init函数执行全局变量初始化初始化包级别的全局变量初始化顺序按变量在代码中声明的顺序执行若有依赖关系如 b 依赖 a则先初始化被依赖的变量。init函数执行执行顺序:同一个包按照包的声明顺序执行不同的包按照包的依赖关系执行全部的init函数在mian函数执行前全部执行并且只执行一次。主逻辑执行初始化完成之后函数进入核心阶段。执行main函数以及main中启动的Goroutine函数启动主Goroutinemain Goroutine创建第一个用户Goroutine(main Goroutine) ,将main 函数作为执行入口。main Goroutine 被加入调度模型分配给某个M 和P执行。调度器工作Go 调度器GPM 模型负责在多个 M系统线程上调度 GGoroutine通过 抢占式调度 实现并发。用户代码执行main 函数中的逻辑如函数调用、循环、条件判断等被翻译成机器码由 M 按指令顺序执行若代码中使用 go 关键字启动新 Goroutine新 G 会被加入调度队列等待执行。并发同步若多个 Goroutine 访问共享资源通过 sync.Mutex、channel 等同步机制协调确保数据安全由运行时负责底层同步支持程序退出main函数执行结束和资源清理回收运行时清理GC 最终回收运行时触发最后一次垃圾回收释放所有未被引用的内存。关闭资源关闭打开的文件、网络连接等资源若用户代码未显式关闭部分资源可能由操作系统回收。销毁 Goroutine终止所有剩余的 Goroutine包括运行时内部的 Goroutine如定时器线程。进程终止运行时调用操作系统的 exit 系统调用终止当前进程释放所有内存和系统资源如文件描述符、网络端口。操作系统回收进程占用的内存和 CPU 资源程序彻底退出。示意图执行二进制文件→ 操作系统加载程序到内存→ Go 运行时初始化内存分配器、调度器、GC 等→ 用户代码初始化全局变量 → init 函数→ 启动 main goroutine执行 main 函数→ 调度器调度 main goroutine 及子 Goroutine 并发执行→ main 函数结束等待子 Goroutine 完成后→ 运行时清理资源GC、关闭连接等→ 进程终止释放所有资源
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进