翻译自
https://www.ardanlabs.com/blog/2018/01/escape-analysis-flaws.html
1 间接赋值
1)创建main,go,内容如下
package main
type X struct {
p *int
}
func main() {
for i := 0; i < 10; i++ {
var i1 int
x1 := &X{
p: &i1,
}
_ = x1
var i2 int
x2 := &X{}
x2.p = &i2
}
}
- go build -gcflags '-m' main.go, 显示
./main.go:17:10: &i2 escapes to heap
./main.go:15:7: moved to heap: i2
./main.go:11:7: main &i1 does not escape
./main.go:11:4: main &X literal does not escape
./main.go:16:9: main &X literal does not escape
2 间接调用
1) 创建main,go,内容如下
package main
func main() {
for i := 0; i < 10; i++ {
var y1 int
foo(&y1, 42)
var y2 int
func(p *int, x int) {
*p = x
}(&y2, 42)
var y3 int
p := foo
p(&y3, 42)
}
}
func foo(p *int, x int) {
*p = x
}
2) go build -gcflags '-m' main.go, 显示
./main.go:19:6: can inline foo
./main.go:6:6: inlining call to foo
./main.go:9:3: can inline main.func1
./main.go:11:4: inlining call to main.func1
./main.go:19:10: foo p does not escape
./main.go:15:5: &y3 escapes to heap
./main.go:13:7: moved to heap: y3
./main.go:6:7: main &y1 does not escape
./main.go:11:5: main &y2 does not escape
3 slice和map 赋值
1) 创建main,go,内容如下
package main
func main() {
for i := 0; i < 10; i++ {
m := make(map[int]*int)
var x1 int
m[0] = &x1 // BAD: cause of x1 escape
s := make([]*int, 1)
var x2 int
s[0] = &x2 // BAD: cause of x2 escape
}
}
2) go build -gcflags '-m' main.go, 显示
./main.go:7:10: &x1 escapes to heap
./main.go:6:7: moved to heap: x1
./main.go:11:10: &x2 escapes to heap
./main.go:10:7: moved to heap: x2
./main.go:5:12: main make(map[int]*int) does not escape
./main.go:9:12: main make([]*int, 1) does not escape
4 interface
1) 创建main,go,内容如下
package main
type Iface interface {
Method()
}
type X struct {
name string
}
func (x X) Method() {}
func main() {
for i := 0; i < 10; i++ {
x1 := X{"bill"}
var i1 Iface = x1
var i2 Iface = &x1
i1.Method() // BAD: cause copy of x1 to escape
i2.Method() // BAD: cause x1 to escape
x2 := X{"bill"}
foo(x2)
foo(&x2)
}
}
func foo(i Iface) {
i.Method() // BAD: cause value passed in to escape
}
2) go build -gcflags '-m' main.go, 显示
./main.go:11:6: can inline X.Method
./main.go:11:7: X.Method x does not escape
./main.go:28:10: leaking param: i
./main.go:16:7: x1 escapes to heap
./main.go:17:7: &x1 escapes to heap
./main.go:17:18: &x1 escapes to heap
./main.go:15:3: moved to heap: x1
./main.go:23:6: x2 escapes to heap
./main.go:24:7: &x2 escapes to heap
./main.go:24:7: &x2 escapes to heap
./main.go:22:3: moved to heap: x2
<autogenerated>:1: leaking param: .this
<autogenerated>:1: (*X).Method .this does not escape
5 未知
1) 创建main,go,内容如下
package main
import "bytes"
func main() {
for i := 0; i < 10; i++ {
var buf bytes.Buffer
buf.Write([]byte{1})
_ = buf.Bytes()
}
}
2) go build -gcflags '-m' main.go, 显示
./main.go:9:16: inlining call to bytes.(*Buffer).Bytes
./main.go:8:6: buf escapes to heap
./main.go:7:7: moved to heap: buf
./main.go:8:19: main []byte literal does not escape
./main.go:9:10: main buf does not escape