Golang中逃逸现象-变量何时 栈何时堆
作者:互联网
变量的逃逸现象
- 将⼀个局部变量的地址返回给上层函数,依然能够访问,那么这个局部变量产⽣的了逃逸现象,当前变量应该并没有分配到栈上。
package main
//inline内联函数
func foo(arg_val int) *int {
var foo_val1 int = 11
var foo_val2 int = 12
var foo_val3 int = 13
var foo_val4 int = 14
var foo_val5 int = 15
//目的是防止编译器优化,优化成内联函数,而不产生foo函数的调用函数
for i := 0; i < 5; i++ {
//为了辨别每个变量的地址是否在栈上还是堆上
println(&arg_val, &foo_val1, &foo_val2, &foo_val3, &foo_val4, &foo_val5)
}
//返回foo_val3的地址给main函数
return foo_val3
}
func main() {
main_val := foo(666)
println(*main_val, main_val)
}
注意:以上函数在C++是编译不通过的,因为C++函数返回后,栈已经清空,这个时候,指针指向一个不存在的领域,则编译不通过
通过Golang编译器分析逃逸现象
-
go tool compile -m demo2.go
通过提示得知哪些变量是被逃逸的
-
编译汇编⽂件
发现foo_val3确实是通过runtime.newobject来开辟,是在堆上,不是栈上,确实发⽣逃逸
new出来的变量是在“栈”还是“堆”?
- golang中的new,创建⼀个空间,未必是在堆上开辟的
结论:Golang中⼀个函数局部变量,不管是不是动态new出来的,还是普通定义出来的,分配到堆上还是栈上,开发者决定不了。⽽是通过编译器做逃逸分析来决定的。
Golang中 new 和 make的区别?
-
相同之处
给变量分配空间的
-
不同之处
make 只是⽤slice、channel、map初始化,⽆可替代 new ⽤于类型的内存分配(初始化是0),不常⽤, 原因 通过“:=”来初始化⽐较常⽤
标签:foo,int,何时,Golang,逃逸,val3,new,main 来源: https://blog.csdn.net/weixin_44879611/article/details/113131710