网站建设灬金手指下拉,杭州网站制作服务,哪个网站做电商门槛最低,4399小游戏网页版入口如何判断变量是分配在栈#xff08;stack#xff09;上还是堆#xff08;heap#xff09;上#xff1f;
Go和C不同#xff0c;Go局部变量会进行逃逸分析。如果变量离开作用域后没有被引用#xff0c;则优先分配到栈上#xff0c;否则分配到堆上。判断语句#xff1a;…如何判断变量是分配在栈stack上还是堆heap上
Go和C不同Go局部变量会进行逃逸分析。如果变量离开作用域后没有被引用则优先分配到栈上否则分配到堆上。判断语句
// -m打印逃逸分析信息 -l禁止内联编译
go build -gcflags -m -m -l xxx.go
通常情况下
栈上函数调用的参数、返回值以及小类型局部变量大都会被分配到栈上这部分内存会由编译器进行管理。无需GC标记
堆上大对象、逃逸的变量会被分配到堆上。分配到堆上的对象Go在运行时GC会在后台将对应的内存进行标记从而能够在垃圾回收的时候将对应的内存回收进而增加了开销。 例子 func main() {a : make([]int, 10000)b : make([]int, 1000)print(a,b)
} 可以看到 a 由于无法被一个执行栈装下即使没有返回也会直接在堆上分配 b 能够被一个执行栈装下变量没有返回到栈外进而没有发生逃逸分配到栈中 指针逃逸分析
局部变量以指针的方式从方法中传出或被全局变量引用这种现象被称为指针逃逸(Escape). 情况一(最基本)在某个函数中new或字面量创建出的变量将其指针作为函数返回值则该变量一定发生逃逸 func main() {c : call2()print(c)
}
func call2() *int {x : 2return x
} 情况二指针作为函数调用参数则该变量如果没有被逃逸的变量或者全局变量引用指针不会逃逸。 func main() {a : make([]int, 5)call(a)
}func call(a *[]int) {(*a)[0] 1
} 情况三仅在函数内对变量做取值操作而未将指针传出指针不会逃逸 func main() {a : 2b : aprint(b) 情况四指针作为函数调用参数则该变量如果被逃逸的变量或者全局变量引用指针会逃逸 var g *intfunc main() {a : 2g a
} 情况五被指针类型的slice、map和chan引用的指针一定会发生逃逸 func main() {a : make([]*int, 1)b : 12a[0] bc : make(map[string]*int)d : 14c[aaa] de : make(chan *int, 1)f : 15e - f
} 总结
golang 变量存储在堆上还是栈上由内部实现决定而和具体的语法没有关系。非指针小对象通常保存在栈上大对象保存在堆上。至于指针保存在堆上还是栈上要进行逃逸分析
指针必然发生逃逸的三种情况
在某个函数中new或字面量创建出的变量将其指针作为函数返回值则该变量一定发生逃逸构造函数返回的指针变量一定逃逸被已经逃逸的变量引用的指针一定发生逃逸被指针类型的slice、map和chan引用的指针一定发生逃逸
一些必然不会逃逸的情况
指针被未发生逃逸的变量引用仅仅在函数内对变量做取址操作而未将指针传出