
函数运行在栈上,栈上声明临时变量分配内存,在函数运行完毕后,回收内存(栈自动回收),每个函数的栈空间都是独立空间,其他函数无法进行访问。
但是在某些情况下,需要栈上面的数据在函数结束后仍然可以被访问,这就涉及到了逃逸。
数据从栈上逃逸,会跑到堆上面。栈上分配内存,需要找到一块大小合适的内存,之后通过GC(Garbage Collection)回收才能释放。
Go实现了gc垃圾回收机制,但gc会影响程序运行性能,所以要尽量减少程序的gc操作.
逃逸分析原则:如果一个函数返回一个对变量的引用,就会发生逃逸。
编译器会分析代码的特征和生命周期。Go中的变量只有在编译器证明函数返回不会被再引用,才会分配到栈上,否则其他情况都是分配到堆上。
简单来说,编译器会根据变量是否被外部引用来决定是否逃逸:
传递指针可以减少底层值的拷贝,可以提高效率,但是如果拷贝的数据量小, 由于指针传递会产生逃逸,可能会使用堆,也可能会增加GC的负担,所以传递指针不一 定是高效的。
package main
type Student struct{
Name string
Age int
}
func StudentRegister(name string, age int) *Student{
s := new(Student)
s.Name = name
s.Age = age
return s
}
func main(){
StudentRegister("jim", 18)
}
很多函数都是interface类型,编译期间很难确定参数的具体类型,也能产生逃逸。
go build-gcflags'-m'
命令来观察变量逃逸情况就行了