逃逸分析(Escape analysis)是指由编译器决定内存分配的位置,不需要程序员指定。 函数中申请一个新的对象如果分配在栈中,则函数执行结束可自动将内存回收;如果分配在堆中,则函数执行结束可交给GC(垃圾回收)处理;
每当函数中申请新的对象,
编译器会跟据该对象是否被函数外部引用来决定是否逃逸:
1. 如果函数外部没有引用,则优先放到栈中;
2. 如果函数外部存在引用,则必定放到堆中.
注意,但然上述表述不是绝对的,对于函数外部没有引用的对象,也有可能放到堆中,比如内存过大超过栈的存储能力。
逃逸检测
当前检测版本
g$ go version
go version go1.13.9 darwin/amd64
package main
import "fmt"
func bar()int{
t :=2
return t
}
func main() {
x :=bar()
fmt.Println(x)
y :=x+1
fmt.Println(y)
}
执行函数
# command-line-arguments
./main.go:11:13: main ... argument does not escape
./main.go:11:13: x escapes to heap
./main.go:13:13: main ... argument does not escape
./main.go:13:13: y escapes to heap
main函数里的x
也逃逸了?这是因为有些函数参数为interface类型,比如fmt.Println(a …interface{}),编译期间很难确定其参数的具体类型,也会发生逃逸。
使用反汇编命令也可以看出变量是否发生逃逸。
go tool compile -S main.go
逃逸分析通常有四种情况: