funcfoo()func() { x := 5// x发生逃逸, 因为在foo调用完成后, 被闭包函数用到, 还不能回收, 只能放到堆上存放 returnfunc() { x += 1 } }
funcmain() { inner := foo() inner() }
// 输出 # command-line-arguments ./test_Demo_04.go:5:6: can inline Foo ./test_Demo_04.go:7:9: can inline Foo.func1 ./test_Demo_04.go:18:14: inlining call to Foo ./test_Demo_04.go:7:9: can inline main.Foo.func1 ./test_Demo_04.go:19:7: inlining call to main.Foo.func1 ./test_Demo_04.go:6:2: moved to heap: x ./test_Demo_04.go:7:9: funcliteralescapestoheap ./test_Demo_04.go:18:14: funcliteraldoesnotescape
在slice或map中存储指针
比如[]*string, 其后面的数组可能是在栈上分配的, 但其引用的值还是堆上;
1 2 3 4 5 6 7 8 9 10 11 12 13
package main
funcmain() { var x int x = 10 var ls []*int ls = append(ls, &x) // x发生逃逸, ls存储的是指针, 所以ls底层的数组虽然在栈上存储, 但本身却逃逸到堆上 }
// 输出 # command-line-arguments ./test_Demo_04.go:5:6: can inline main ./test_Demo_04.go:11:6: moved to heap: x
4. 切片扩容
切片扩容后长度太长, 导致栈空间不足, 逃逸到堆上;
1 2 3 4 5 6 7 8 9 10 11 12 13
package main
funcmain() { s := make([]int, 10000, 10000) for index, _ := range s { s[index] = index } }
// 输出 # command-line-arguments ./test_Demo_04.go:5:6: can inline main ./test_Demo_04.go:11:11: make([]int, 10000) escapes to heap
funcmain() { var f foo1 f = foo1{} f.fooFunc() // 调用方法时, f发生逃逸, 因为方法是动态分配的 }
// 输出 # command-line-arguments ./test_Demo_04.go:12:6: can inline foo1.fooFunc ./test_Demo_04.go:16:6: can inline main <autogenerated>:1: inlining call to foo1.fooFunc ./test_Demo_04.go:18:10: foo1{} escapes to heap