文章目录
1.概述
在本系列的前一篇文章中,详细介绍了C语言的函数栈技术。
函数栈深入解析(1) - C语言函数栈
本文章我们再来剖析一下 Go语言函数栈技术。
Go语言采用动态栈技术管理函数调用栈。每个goroutine初始分配2KB连续栈空间,运行时根据需求自动扩容(复制到更大内存区)或缩容,避免栈溢出并提升内存效率。相比传统固定栈(如C语言),动态栈支持更深的递归和灵活并发,由运行时系统透明管理栈分配,消除了分段栈的性能碎片问题,保障了轻量级高并发特性。
2.示例入门
参考下面这段go代码(main.go),仅有2个函数。一个是主函数main,一个是自定义的函数add。
package main
func add(a, b int) int {
return a + b
}
func main() {
add(1, 2)
}
将此文件,编译为汇编代码:go tool compile -S -N -l main.go
编译选项:
-S: 生成汇编代码并输出到标准输出。该选项指示编译器在编译后不生成目标文件(.o),而是输出对应的汇编代码(Plan 9 格式),方便开发者查看程序底层的实现。
-N:禁用编译优化。默认情况下,Go 编译器会进行多种优化以提高代码性能。使用 -N 会关闭这些优化,生成的代码更贴近源代码结构,便于调试(例如避免变量被优化掉)。
-l: 禁用内联(Inlining)。默认情况下,编译器会将小函数内联展开以减少函数调用开销。使用 -l 会禁止内联,保持函数调用的独立性,便于分析函数调用关系或调试。
得到如下汇编信息:
main.add STEXT nosplit size=49 args=0x10 locals=0x10 funcid=0x0 align=0x0
0x0000 00000 (main.go:3) TEXT main.add(SB), NOSPLIT|ABIInternal, $16-16
0x0000 00000 (main.go:3) SUBQ $16, SP
0x0004 00004 (main.go:3) MOVQ BP, 8(SP)
0x0009 00009 (main.go:3) LEAQ 8(SP), BP
0x000e 00014 (main.go:3) FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x000e 00014 (main.go:3) FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x000e 00014 (main.go:3) FUNCDATA $5, main.add.arginfo1(SB)
0x000e 00014