底层逻辑 - 理解 Go 语言的本质
1.Java VS Go 语言
Java,从源代码到编译成可运行的代码
上图已经展示了这个过程:从 Java 的源代码编译成 jar 包或 war 包(字节码),最终运行在 JVM 中。
我们把 Java 源代码编译后的 jar 包或 war 包看成是工程师生产出来的产品,操作系统是一个平台,JVM 就是中间商,那程序的整体性能也要受到中间商 JVM 的因素影响了。
优点:一次编译,到处运行(windows、linux、macos)
缺点:JVM 性能损失大。
Go 语言,从源代码到编译成可运行的代码
我们把 Go 语言的源代码编译后,生成二进制文件,直接就可以在操作系统上运行,没有中间商。
优点:
直接编译成二进制
无需进行虚拟机环境,自动执行
一次编写代码,跨平台执行
高性能并发能力
2.为什么 Go 语言运行-"没有中间商"
每种编程语言都有自己的 Runtime, 把这个单词拆开来看,Run=运行,Time=时间,简称:运行时。
Go 语言的 Runtime 作用:
内存管理
协程调度
垃圾回收
Go 语言的运行时,是和源代码最终编译生成到二进制文件中的。当我们启动二进制文件的时候,运行时也就是一并启动了。
Go 语言是如何编译成二进制文件的
在命令行执行 go build -n(-n 含义代表:打印编译时会用到的所有命令,但不真正执行)
编译过程 1
从上图可以看到:
import config 导入配置
fmt.a--->对应 fmt 包
runtime.a--->对应 runtime 包
compile -o 编译输出到 pkg.a
编译过程 2
创建 exe 目录
link 链接到 a.out
把 a.out 该名成 menu1
总结:看到上面的过程已经把 runtime 包放到我们的二进制文件中了。
3.编译过程
在编译原理中,有一个名词:AST(抽象语法树) = Abstract Syntax Tree1. 把源代码变成文本,然后把每个单词拆分出来 2. 把每个单词变成语法树 3. 类型检查、类型推断、类型匹配、函数调用、逃逸分析
分析阶段
词法检查分析、语法检查分析、语义检查分析)
生成中间码生成(SSA 代码,类似汇编)。
执行export GOSSAFUNC=main,代表你要看main函数的ssa代码,然后执行go build,会生成ssa.html
图 1.图 2.
代码优化
生成机器码(支持生成.a 的文件)
go build -gcflags -S main.go(生成和平台相关的 plan9 汇编代码)
链接(生成可执行二进制文件)
4.Go 语言是如何启动的
Go 语言启动的时候,Runtime 到底发生了什么?
可以到 runtime 目录中找到 rt0_darwin_amd64.s 找到这个文件(由于我的电脑是 mac,所以找到了这个,其他平台可以找各自的),这是一个汇编文件。
rt0_darwin_amd64.s
asm_amd64.s
接下来在同名文件中找到
它执行
在堆栈上复制参数。
从给定的(操作系统)堆栈中创建 iStack。
_cgo_init(可能会更新堆栈保护)
收集用到的处理器信息
上面信息就是初始化一个协程 G0(这是一个根协程,此时还没有调度器,也就是说不受调度器控制)
接下来是各种平台的检测和判断
查找代码 在 runtime1.go,很亲切的 Go 语言函数了吧。里面是各种检查。看看都干了啥。
上面代码执行了:
检查类型长度是否合法
检查偏移量是否合法
检查 CAS 执行是否合法
检查原子执行是否合法
检查指针执行是否合法
判断栈大小是否是 2 的幂次方
接下来
下面看一下启动顺序:osinit(操作系统的初始化) -> schedinit(调度器的初始化) -> make & queue new G(新建一个队列 G) -> mstart(启动)
runtime/proc.go
可以看到上面的代码的操作:
CPU 初始化
栈空间初始化
堆空间初始化
命令行参数初始化
环境变量初始化
GC 初始化
从上面看到,此时系统里拥有:
G0-根协程
runtime.main 的主协程
启动了 M 等待调度
runtime.main 在 runtime/proc.go 中(这个是 runtime 中的 main 方法,还没到我们自己写的 main 函数)
从上面看到:
getg() 获取当前的 goroutine
对 g 做判断和设置操作
初始化 runtime doInit(...)
启用 GC
fn := main_main 这是隐式的调用,因为 linker 运行时不知道主包的地址。在之前的学习,我们知道编译过程有链接的时候,就会从 main_main 去找 main.main。这个时候,才真正执行到我们程序员写的代码中。 go:linkname main_main main.main
版权声明: 本文为 InfoQ 作者【面向加薪学习】的原创文章。
原文链接:【http://xie.infoq.cn/article/5ba15bb7d1529120b048d8dd2】。文章转载请联系作者。
评论