面试题答案
一键面试常见导致内存逃逸的情况及代码示例
- 返回局部变量指针
package main
func allocate() *int {
num := 10
return &num
}
在上述代码中,allocate
函数返回了局部变量 num
的指针。由于函数返回后,调用者可能还会使用这个指针,所以 num
不能在栈上分配,只能逃逸到堆上。
- 传递给接口类型参数
package main
type Number interface{}
func passToInterface(i Number) {}
func main() {
num := 10
passToInterface(num)
}
这里 num
被传递给了 passToInterface
函数,其参数类型是接口类型 Number
。因为在编译时无法确定 num
在接口中的具体使用方式,所以 num
会逃逸到堆上。
- 动态大小的切片
package main
func growSlice() []int {
var s []int
for i := 0; i < 10; i++ {
s = append(s, i)
}
return s
}
在 growSlice
函数中,s
是一个动态大小的切片。由于切片的大小在编译时不确定,并且在函数执行过程中可能会不断增长,所以 s
会逃逸到堆上。
借助工具判断内存逃逸现象
在Go中,可以使用 go build
命令的 -gcflags
选项来查看内存逃逸分析结果。例如:
go build -gcflags '-m'
执行上述命令后,编译输出中会包含逃逸分析信息,如下所示:
# command-line-arguments
./main.go:4:13: &num escapes to heap
./main.go:3:6: moved to heap: num
上述输出表明 num
变量逃逸到了堆上。如果想获取更详细的信息,可以使用 -m -m
选项,即:
go build -gcflags '-m -m'
这样会输出更详细的逃逸分析信息,帮助开发者更准确地定位和理解内存逃逸问题。