代码
main.go 文件
package main
import "fmt"
func main() {
data := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
}
res := make(map[string]*int, 4)
for k, v := range data {
res[k] = &v
}
for k, v := range res {
fmt.Println(k, *v)
}
}
上述代码的输出结果是什么?
a 4
b 4
c 4
d 4
解释
上述代码中,发生了内存逃逸
for k, v := range data {
res[k] = &v
}
因为for 循环遍历过程中,v为指针变量,并且在for循环结束后还需要用到 res[k] = &v 。因此会发生内存逃逸,v会被分配到对空间上。每次遍历过程中,v都指向同一块内存地址,因此res[k]所有的value值为最后一次遍历的v。
查看逃逸分析
go build -gcflags "-m -l" main.go
$ go build -gcflags "-m -l" main.go
# command-line-arguments
.\main.go:13:9: moved to heap: v
.\main.go:6:24: map[string]int{...} does not escape
.\main.go:12:13: make(map[string]*int, 4) does not escape
.\main.go:17:14: ... argument does not escape
.\main.go:17:14: k escapes to heap
.\main.go:17:18: *v escapes to heap
第三行 .\main.go:13:9: moved to heap: v,局部变量v被分配到了堆空间上。
【注】最后两行显示发生了内存逃逸,这是因为fmt.Println()的函数的参数是空接口,也会发生内存逃逸。