栈内存&堆内存&逃逸分析
目录
1. 栈内存
栈内存由
编译器自动分配和释放
,开发者无法控制。栈内存一般存储函数
中的局部变量、参数等
,函数创建的时候,这些内存会被自动创建;函数返回的时候,这些内存会被自动释放。
2. 堆内存
堆分配内存和栈分配内存相比,
堆适合不可预知大小的内存分配
。但是为此付出的代价是分配速度较慢,而且会形成内存碎片 。
堆内存的生命周期比栈内存要长
,如果函数返回的值还会在其他地方使用,那么这个值就会被编译器自动分配到堆上。堆内存相比栈内存来说,不能自动被编译器释放,只能通过垃圾回收器才能释放,所以栈内存效率会很高。
3. 逃逸分析
栈内存的效率更高,肯定是优先使用栈内存。那么
Go
语言是如何判断一个变量应该分配到堆上还是栈上的呢?这就需要逃逸分析了。
package main
func main() {
newString()
}
func newString() *string{
s:=new(string)
*s = "wohu"
return s //返回指针,发生逃逸
}
go build -gcflags="-m -l" demo.go
# -m 表示打印出逃逸分析信息;
# -l 表示禁止内联,可以更好地观察逃逸;
指针作为函数返回值的时候,一定会发生逃逸。
逃逸到堆内存的变量不能马上被回收,只能通过垃圾回收标记清除
,增加了垃圾回收的压力,所以要尽可能地避免逃逸,让变量分配在栈内存上,这样函数返回时就可以回收资源,提升效率。要学会重用内存,比如使用
sync.Pool
func newString() string{
s:=new(string)
*s = "wohu"
return *s //返回数值,没有发送逃逸
}