go内存逃逸
逃逸分析
go在编译时确定是否逃逸,逃逸分析是编译器决定变量分配到栈上还是堆上的一种行为。
查看逃逸分析日志:go build -gcflags=-m
其中,-m打印出逃逸分析的优化策略。
指针逃逸
函数局部变量优先分配到栈上。
如果编译器不能确保变量在函数return之后不再被引用,那么编译器就会将变量分配到堆上。
如果一个局部变量非常大,那么它会被分配到堆上。
函数传递指针比传值效率高吗?
传递指针可以减少底层值的拷贝。如果拷贝的数据量小,那么指针传递会产生逃逸,使用堆,增加GC负担,所以传递指针不一定是高效的。
package main
type A struct {
a int
}
func getA() *A {
s := new(A)
s.a = 10
return s
}
func main() {
getA()
}
栈空间不足逃逸
当栈空间不足以存放当前对象或无法判断当前切片长度时会将对象分配到堆中。
package main
func main() {
s := make([]int, 10000, 10000)
for i, _ := range s {
s[i] = i
}
}
动态类型逃逸
函数参数是interface类型,编译时很难确定参数的具体类型,会产生逃逸。
func Print(a ...interface{}) (n int, err error)
func Println(a ...interface{}) (n int, err error)
package main
import "fmt"
func main() {
fmt.Print("a")
fmt.Println("b")
}