// noescape hides a pointer from escape analysis. noescape is // the identity function but escape analysis doesn't think the // output depends on the input. noescape is inlined and currently // compiles down to zero instructions. // USE CAREFULLY! //go:nosplit funcnoescape(p unsafe.Pointer)unsafe.Pointer { x := uintptr(p) return unsafe.Pointer(x ^ 0) }
举例
通过一个例子加深理解,接下来尝试下怎么通过 go build -gcflags=-m 查看逃逸的情况。
$go build -gcflags=-m main.go # command-line-arguments ./main.go:11:6: can inline (*A).String ./main.go:19:6: can inline (*ATrick).String ./main.go:23:6: can inline NewA ./main.go:31:6: can inline noescape ./main.go:27:6: can inline NewATrick ./main.go:28:29: inlining call to noescape ./main.go:36:6: can inline main ./main.go:38:14: inlining call to NewA ./main.go:39:19: inlining call to NewATrick ./main.go:39:19: inlining call to noescape ./main.go:40:17: inlining call to (*A).String ./main.go:41:17: inlining call to (*ATrick).String /var/folders/45/qx9lfw2s2zzgvhzg3mtzkwzc0000gn/T/go-build763863171/b001/_gomod_.go:6:6: can inline init.0 ./main.go:11:7: leaking param: f to result ~r0 level=2 ./main.go:19:7: leaking param: f to result ~r0 level=2 ./main.go:24:16: &s escapes to heap ./main.go:23:13: moved to heap: s ./main.go:27:18: NewATrick s does not escape ./main.go:28:45: NewATrick &s does not escape ./main.go:31:15: noescape p does not escape ./main.go:38:14: main &s does not escape ./main.go:39:19: main &s does not escape ./main.go:40:10: main f1 does not escape ./main.go:41:10: main f2 does not escape ./main.go:42:9: main s1 + s2 does not escape
其中主要看中间一小段
1 2 3 4
./main.go:24:16: &s escapes to heap //这个是NewA中的,逃逸了 ./main.go:23:13: moved to heap: s ./main.go:27:18: NewATrick s does not escape // NewATrick里的s的却没逃逸 ./main.go:28:45: NewATrick &s does not escape