自动决定变量分配在栈还是堆——Escape Analysis
在c/c++语言中,需要开发者学习如何进行内存分配,选用什么样的内存分配方式来适应不同的算法 要求,比如,函数局部变量尽量使用栈,全局变量使用堆分配等。go语言将整个过程整合到编译器中,由编译器分析代码的特征和代码生命周期,决定是使用堆还是栈进行内存分配。
看两个简单的例子,看下分析结果,使用 **go run -gcflags “-m -l” main.go,**在go运行时,-gcflags参数是编译参数,其中-m 是表示进行内存分配分析,-l 表示避免程序内联,也就是避免进行陈序优化。
1、是否发生逃逸
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package main
import "fmt"
func calc(a, b int) int {
c := a + b
var x int
x = c * 10
return x
}
func main() {
m := calc(3, 2)
fmt.Println(m)
}
|
执行go run -gcflags “-m -l” main.go后,输出结果如下:
1
2
3
4
|
➜ testEscape go run -gcflags "-m -l" main.go
# command-line-arguments
./main.go:15:13: m escapes to heap
./main.go:15:13: main ... argument does not escape
|
可以看到“m escapes to heap”,m变量到了堆内存,发生了逃逸,因为m是calc的返回值,但后面 被fmt.Println使用。
2、是否被取址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package main
import "fmt"
func calc(a, b int) *int {
c := a + b
var x int
x = c * 10
return &x
}
func main() {
m := calc(3, 2)
fmt.Println(*m)
}
|
输出如下:
1
2
3
4
|
./main.go:10:9: &x escapes to heap
./main.go:7:6: moved to heap: x
./main.go:15:14: *m escapes to heap
./main.go:15:13: main ... argument does not escape
|
我们看到,第三行输出:moved to heap: x,x也move到heap。
内存分配在栈还是堆上看下面的两个条件:
1、是否被取址 :如果被取址,则分配在堆内存
2、是否发生逃逸 :发生逃逸,则分配在堆内存上面
知道这个有啥用呢,哈哈 ,这样看到闭包就不害怕了