Go 没有手动堆栈分配语法,由编译器的逃逸分析决定:如果变量的生命周期超出函数作用域(被返回、被闭包捕获、赋给接口、尺寸过大或动态决定),它就'逃逸'到堆上,由 GC 管理;否则分配在栈上,随函数返回自动回收,几乎零成本。
常见逃逸场景:返回局部变量的指针;把值赋给 interface{} 参数(如 fmt.Println 的实参在旧版本中逃逸,新版有优化);闭包引用外层变量;slice/map 容量在编译期不确定。栈分配的优势是分配和回收都只是移动栈指针,不产生 GC 压力,所以减少逃逸是 Go 性能优化的常规手段。
go build -gcflags='-m -m' main.go
# ./main.go:10:2: moved to heap: x
func stack() int { x := 1; return x } // x 留栈
func heap() *int { x := 1; return &x } // x 逃逸到堆
易错点:逃逸分析是编译期静态决策,不同 Go 版本结论可能变化,不要依赖具体行为;为'避免逃逸'而牺牲代码可读性通常不值得,先用 pprof 确认分配热点。追问方向:栈的连续增长与栈拷贝、内联对逃逸分析的影响。