package main
type S struct {}
func main() {
var x S
_ = identity(x)
}
func identity(x S) S {
return x
}
你可以执行go run -gcflags '-m -l'(注:原文中略了go代码文件名)来编译这个代码,-l参数是防止函数identity被内联(换个时间再讨论内联这个话题)。你将会看到没有任何输出!Go使用值传递,所以main函数中的x这个变量总是会被拷贝到函数identity的栈空间。通常情况下没有使用引用的代码都是通过栈空间来分配内存。所以不涉及逃逸分析。下面试下困难一点的:
package main
type S struct {}
func main() {
var x S
y := &x
_ = *identity(y)
}
func identity(z *S) *S {
return z
}
其对应的输出是:
./escape.go:11: leaking param: z to result ~r1
./escape.go:7: main &x does not escape
package main
type S struct {
M *int
}
func main() {
var x S
var i int
ref(&i, &x)
}
func ref(y *int, z *S) {
z.M = y
}
其输出为:
./escape.go:13: leaking param: y
./escape.go:13: ref z does not escape
./escape.go:9: moved to heap: i
./escape.go:10: &i escapes to heap
./escape.go:10: main &x does not escape