三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

go 内存逃逸分析

go 内存逃逸分析

目录

一、什么是逃逸分析

二、为什么需要逃逸分析?

三、逃逸发生的常见场景

1. 返回局部变量的指针

2. 将变量赋值给包级全局变量或外部引用的指针

3. 将变量传递给 interface{} 参数(可能逃逸,取决于函数内是否存储引用)-不必要

改正方法

4. 闭包捕获变量

5. 切片或 map 存储指针(或本身需要扩容)-不必要

改正方法

6. 发送到 channel 的指针

三、如何查看逃逸分析结果?

四、逃逸分析与栈分配的关系图

五、性能影响与优化建议

性能差异

优化建议

六、典型反例:循环中取地址

七、常见的坑

八、总结


一、什么是逃逸分析

逃逸分析 是 Go 编译器在编译阶段执行的一项静态分析技术,用于判断一个变量的内存是分配在栈上还是堆上。

它的核心结论是:如果变量在函数返回后仍然可能被引用,则它会“逃逸”到堆上;否则,它优先分配在栈上。


二、为什么需要逃逸分析?

分配位置优点缺点
栈上分配分配/释放极快(仅移动栈指针),无需 GC 扫描函数返回后自动销毁,无法跨函数保持
堆上分配可跨函数访问,生命周期灵活分配较慢,需要 GC 管理,增加 GC 压力

逃逸分析的目标:尽量把变量分配在栈上,减少堆分配,从而降低 GC 负担、提升性能。


三、逃逸发生的常见场景

1.返回局部变量的指针

func newInt() *int { x := 42 return &x // x 逃逸到堆上,因为返回后仍需访问 }

2.将变量赋值给包级全局变量或外部引用的指针

var global *int func setGlobal() { x := 42 global = &x // x 逃逸到堆上 }

3.将变量传递给 interface{} 参数(可能逃逸,取决于函数内是否存储引用)-不必要

func printInterface(v interface{}) { fmt.Println(v) } func main() { x := 42 printInterface(x) // x 可能逃逸,因为 interface{} 可能持有引用 }

为什么会逃逸?

  • interface{} 是一个包含类型和指

← 返回列表