进行逃逸分析,将 var(s) 声明为指针

Go escape analysis, with var(s) declared as pointers

func main() {
 var cs CustomStruct
 r := []byte{.......}
 err:=proto.Unmarshal(r, &cs)
 if err!=nil {
    panic(err)
  } 
}

当我运行go build -gcflags="-m" ./... 时,我得到

moved to heap: CustomStruct

但是稍作改动,它就不会移动到堆中:

func main() {
 var cs *CustomStruct
 r := []byte{.......}
 err:=proto.Unmarshal(r, cs)
 if err!=nil {
    panic(err)
  } 
}

现在当我 运行 逃逸分析命令时,它并没有说 CustomStruct 被移动到堆中。这到底是怎么回事?

由于 cs 的地址被发送到一个函数,并且该函数可能会在函数 returns 之后生成可能持有对 cs 的引用的 goroutines,因此它被移动到堆.

在第二种情况下,cs是一个指针。不需要把指针本身移到堆上,因为函数Unmarshal可以引用的是cs指向的对象,而不是cs本身。您没有显示 cs 是如何初始化的,因此这段代码将失败,但是如果您将 cs 初始化为指向该函数中声明的变量,该对象可能最终会出现在堆中.

proto.Unmarshal

func Unmarshal(buf []byte, pb Message)
type Message interface {
    Reset()
    String() string
    ProtoMessage()
}

interface{}可以是任何类型,编译时很难确定其参数的具体类型,也会出现escape。

但是如果 interface{} 是一个指针,它只是一个指针