NOTE

3.2 逃逸分析

1. 逃逸分析 如果是Java或C++创建出来的对象一般都是分配在堆上的,而Golang new出来的对象会根据逃逸分析决定是分配在堆还是栈上 2. 为什么需要逃逸分析 堆 栈 --- ----------- ------------- 回收 需要垃圾回收 退出函数即销毁 空间 大 小 3. 如何逃

Go创建于 更新于 historical

这是历史学习笔记,可能存在过时或不完整的理解。

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)

5. 参考