NOTE
3.2 逃逸分析
1. 逃逸分析 如果是Java或C++创建出来的对象一般都是分配在堆上的,而Golang new出来的对象会根据逃逸分析决定是分配在堆还是栈上 2. 为什么需要逃逸分析 堆 栈 --- ----------- ------------- 回收 需要垃圾回收 退出函数即销毁 空间 大 小 3. 如何逃
这是历史学习笔记,可能存在过时或不完整的理解。
1. 逃逸分析
如果是Java或C++创建出来的对象一般都是分配在堆上的,而Golang new出来的对象会根据逃逸分析决定是分配在堆还是栈上
2. 为什么需要逃逸分析
| 堆 | 栈 | |
|---|---|---|
| 回收 | 需要垃圾回收 | 退出函数即销毁 |
| 空间 | 大 | 小 |
3. 如何逃逸分析
如果函数外部没有引用,则优先放到栈中; 如果函数外部存在引用,则必定放到堆中;
2026 注:这两条适合作为当时的简化理解,不是编译器的绝对规则。实际是否逃逸以当前 Go 编译器的分析结果为准。
4. 例子
package main
import "fmt"
func foo() *int {
t := 3
return &t;
}
func main() {
x := foo()
fmt.Println(*x)
}
go build -gcflags '-m -l' main.go
# command-line-arguments
//t逃逸了,没有问题
.\main.go:6:2: moved to heap: t
.\main.go:12:13: main ... argument does not escape
//x也逃逸了?函数参数为interface类型,比如fmt.Println(a ...interface{}),编译期间很难确定其参数的具体类型,也会发生逃逸
.\main.go:12:14: *x escapes to heap
go tool compile -S test.go | grep -i "test.go:6"
0x0024 00036 (test.go:6) PCDATA $0, $1
0x0024 00036 (test.go:6) PCDATA $1, $0
0x0024 00036 (test.go:6) LEAQ type.int(SB), AX
0x002b 00043 (test.go:6) PCDATA $0, $0
0x002b 00043 (test.go:6) MOVQ AX, (SP)
0x002f 00047 (test.go:6) CALL runtime.newobject(SB)//newobject看出x逃逸了
0x0034 00052 (test.go:6) PCDATA $0, $1
0x0034 00052 (test.go:6) MOVQ 8(SP), AX
0x0039 00057 (test.go:6) MOVQ $3, (AX)