所谓逃逸分析(Escape analysis),是指由编译器进行内存分配策略分析, 通过编译参数-gcflag=-m可以查看编译过程中的逃逸分析。
如:

1
go build -gcflags="-m"

一般的,函数申请一个对象可能存放在堆或栈中

如果分配在栈中,则函数执行结束可自动将内存回收;
如果分配在堆中,则函数执行结束可交给GC(垃圾回收)处理;

编译器跟据对象是否被函数外部引用来决定存放位置:

如果函数外部没有引用,则优先放到栈中;
如果函数外部存在引用,则必定放到堆中;

如下面一段代码escape.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

type One struct {
Name string
}

func OneRegister(name string) *One {
s := new(One) //局部变量s逃逸到堆
s.Name = name
return s
}

func main() {
OneRegister("Jim Green")
}

在执行编译命令后提示“escapes to heap”,表示该行内存分配发生了逃逸现象。

1
2
3
4
5
6
7
8
9
go build -gcflags="-m" escape.go 

# command-line-arguments
./escape.go:7:6: can inline OneRegister
./escape.go:13:6: can inline main
./escape.go:14:13: inlining call to OneRegister
./escape.go:7:18: leaking param: name
./escape.go:8:10: new(One) escapes to heap
./escape.go:14:13: main new(One) does not escape