这段代码中,初看起来貌似在 main 函数中(不考虑 newFuncContainer 函数中导致的内存分配)没有运行时内存分配(m 会被优化成全局区,所以不会真的导致运行时内存分配),但是实际上在 main 中是有两次运行时内存分配的,这是怎么回事呢?
函数还能逃逸到堆上?
我们用-gcflags="-m"来打印一下编译器的优化信息,可以看到:
1 2 3 4 5 6 7
./main.go:13:7: m does not escape ./main.go:32:23: leaking param: f ./main.go:33:7: &myFuncContainer literal escapes to heap ./main.go:39:7: &myFuncImplStruct literal escapes to heap ./main.go:42:26: m.myFunc escapes to heap ./main.go:43:27: m2.myFunc2 escapes to heap <autogenerated>:1: .this does not escape
funcmain() { // direct call of top-level func TopLevel(1)
// direct call of method with value receiver (two spellings, but same) var v Value v.M(1) Value.M(v, 1)
// direct call of method with pointer receiver (two spellings, but same) var p Pointer (&p).M(1) (*Pointer).M(&p, 1)
// indirect call of func value (×4) f1 := TopLevel f1(1) f2 := Value.M f2(v, 1) f3 := (*Pointer).M f3(&p, 1) f4 := literal f4(1)
// indirect call of method on interface (×3) var i Interface i = v i.M(1) i = &v i.M(1) i = &p i.M(1) Interface.M(i, 1) Interface.M(v, 1) Interface.M(&p, 1) }
注意上述 LEAQ type.noalg.struct { F uintptr; R *"".myFuncImplStruct }(SB), AX这段代码,咱也别管啥意思,反正看到了一个和之前说的适配器很像的一个 struct,这个 struct 有两个字段,第一个是F uintptr,第二个是R *myFuncImplStruct;下面还有一个LEAQ type.noalg.struct { F uintptr; R "".myFuncImplStruct }(SB), AX,只不过这里的 R 是myFuncImplStruct的值而不是指针,这正好和我们代码吻合。
这段代码中,初看起来貌似在 main 函数中(不考虑 newFuncContainer 函数中导致的内存分配)没有运行时内存分配(m 会被优化成全局区,所以不会真的导致运行时内存分配),但是实际上在 main 中是有两次运行时内存分配的,这是怎么回事呢?
函数还能逃逸到堆上?
我们用-gcflags="-m"来打印一下编译器的优化信息,可以看到:
1 2 3 4 5 6 7
./main.go:13:7: m does not escape ./main.go:32:23: leaking param: f ./main.go:33:7: &myFuncContainer literal escapes to heap ./main.go:39:7: &myFuncImplStruct literal escapes to heap ./main.go:42:26: m.myFunc escapes to heap ./main.go:43:27: m2.myFunc2 escapes to heap <autogenerated>:1: .this does not escape
funcmain() { // direct call of top-level func TopLevel(1)
// direct call of method with value receiver (two spellings, but same) var v Value v.M(1) Value.M(v, 1)
// direct call of method with pointer receiver (two spellings, but same) var p Pointer (&p).M(1) (*Pointer).M(&p, 1)
// indirect call of func value (×4) f1 := TopLevel f1(1) f2 := Value.M f2(v, 1) f3 := (*Pointer).M f3(&p, 1) f4 := literal f4(1)
// indirect call of method on interface (×3) var i Interface i = v i.M(1) i = &v i.M(1) i = &p i.M(1) Interface.M(i, 1) Interface.M(v, 1) Interface.M(&p, 1) }
注意上述 LEAQ type.noalg.struct { F uintptr; R *"".myFuncImplStruct }(SB), AX这段代码,咱也别管啥意思,反正看到了一个和之前说的适配器很像的一个 struct,这个 struct 有两个字段,第一个是F uintptr,第二个是R *myFuncImplStruct;下面还有一个LEAQ type.noalg.struct { F uintptr; R "".myFuncImplStruct }(SB), AX,只不过这里的 R 是myFuncImplStruct的值而不是指针,这正好和我们代码吻合。