面试题答案
一键面试内存逃逸情况
- 切片返回给调用者:当在函数内部创建一个切片,然后将该切片返回给调用者时,如果切片的底层数组在函数返回后仍然需要被访问,那么这个底层数组可能会发生内存逃逸,从栈上逃逸到堆上。因为栈上的内存空间在函数结束时会被释放,如果底层数组还需要在函数外部使用,就必须分配到堆上。
- 切片作为参数传递给可能会延长其生命周期的函数:比如传递给一个会将切片存储在全局变量或者持久化数据结构中的函数。如果函数内部对切片的操作使得切片的生命周期超出了当前函数的栈空间范围,那么切片底层数组也会发生内存逃逸。
简单场景示例
package main
import "fmt"
func createSlice() []int {
s := make([]int, 5)
for i := 0; i < 5; i++ {
s[i] = i
}
return s
}
func main() {
result := createSlice()
fmt.Println(result)
}
在上述代码中,createSlice
函数内部创建了一个切片 s
,并将其返回。由于 s
会在函数外部被使用(main
函数中打印 result
),所以 s
的底层数组会发生内存逃逸,从栈逃逸到堆上。可以通过 go build -gcflags '-m -l'
命令查看逃逸分析信息,会看到类似 createSlice: make([]int, 5) escapes to heap
的提示,表明 make([]int, 5)
操作导致内存逃逸到堆上。