文章目录
- func createInt() *int { x := 42 // x 逃逸到堆上 return &x }
- var global *int func escapeToGlobal() { x := 100 global = &x // x 逃逸到堆上 }
- func sendPointer(ch chan *int) { x := 200 ch <- &x // x 逃逸到堆上 }
- func closureExample() func() int { x := 300 return func() int { // x 逃逸到堆上 return x } }
- type Writer interface { Write([]byte) (int, error) } func storeInterface() { buf := bytes.Buffer{} // buf 可能逃逸 var w Writer = &buf _ = w }
目录
- 逃逸分析的基本原则
- 常见的逃逸情况
- 1. 返回局部变量的指针
- 2. 将指针存入全局变量或包级变量
- 3. 发送指针到 channel
- 4. 在闭包中捕获变量
- 5. 存储到接口类型的变量
- 不会逃逸的情况
- 1. 局部变量仅在函数内使用
- 2. 小的切片和映射(通常栈分配)
- 查看逃逸分析结果
- 逃逸分析的意义
- 编译器优化技巧
Go 语言的逃逸分析是在编译阶段进行的静态分析过程,用于确定变量的内存分配位置(栈还是堆)。
基本规则:如果变量的生命周期超出了函数调用的范围,就会发生逃逸,变量被分配到堆上。
func createInt() *int {
x := 42 // x 逃逸到堆上
return &x
}
var global *int
func escapeToGlobal() {
x := 100
global = &x // x 逃逸到堆上
}
func sendPointer(ch chan *int) {
x := 200
ch <- &x // x 逃逸到堆上
}
func closureExample() func() int {
x := 300
return func() int { // x 逃逸到堆上
return x
}
}
type Writer interface {
Write([]byte) (int, error)
}
func storeInterface() {
buf := bytes.Buffer{} // buf 可能逃逸
var w Writer = &buf
_ = w
}
func noEscape() int {
x := 42 // 分配在栈上
return x
}
func smallAllocation() {
s := make([]int, 10) // 可能在栈上
m := make(map[int]int) // 可能在栈上
_ = s
_ = m
}
使用 -gcflags="-m" 标志编译:
go build -gcflags="-m" main.go
输出示例:
./main.go:10:6: can inline createInt ./main.go:11:2: moved to heap: x # x 逃逸到堆 ./main.go:20:2: x escapes to heap # x 逃逸到堆
- 性能优化:减少堆分配,降低 GC 压力
- 内存安全:确保悬挂指针不会访问无效内存
- 自动内存管理:开发者无需手动管理栈/堆分配
现代 Go 编译器会进行深度优化:
- 内联优化:小函数内联可能改变逃逸分析结果
- 标量替换:将结构体分解为基本类型,避免逃逸
- 逃逸分析迭代:多次分析以获得最优结果
Go 的逃逸分析是编译器自动进行的,开发者只需关注代码逻辑,编译器会智能地决定最佳的内存分配策略。
到此这篇关于浅谈Go 语言中逃逸分析是怎么进行的的文章就介绍到这了,更多相关Go 逃逸分析内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
您可能感兴趣的文章:
- GoLang 逃逸分析的机制详解
- Golang内存管理之内存逃逸分析
- 一文带你搞懂golang中内存分配逃逸分析
- 详解Go语言中的逃逸分析
- Go语言中的逃逸分析究竟是什么?
- 浅析Go语言中的逃逸分析
- Golang学习之内存逃逸分析
- 浅析Go语言中的逃逸分析
- Go逃逸分析示例详解