在Go中返回结构成员或嵌入式结构上的指针?

时间:2017-03-20 19:42:54

标签: pointers go struct heap

获取地址并将指针返回到Go中函数内的局部变量会导致编译器将其分配到堆而不是堆栈,以使返回的指针保持有效。

如果我接受并返回结构成员或嵌入式结构的地址会发生什么?

type A struct {
    a,b,c int
}
type B struct {
    A
    d,e,f int
}
func (b *B) get1() *A {
    return &b.A
}
func (b *B) get2() *A {
    localB := B{}
    return &localB.A
}

编译器是否会在堆上分配嵌入式结构A并将B的成员保留在堆栈上?

即使localB.A引用仍在使用中,垃圾收集器是否会收集localB?

如果通过反射访问嵌入式结构,编译器如何确定何时将嵌入式结构保留在堆栈或堆上?

2 个答案:

答案 0 :(得分:3)

为什么你甚至想知道这些细节?

引用Go FAQ(强调我的):

  

从正确的角度来看,你不需要知道。每个变量   只要有引用就存在于Go中。存储   位置由实现选择与语义无关   语言。

  

在当前的编译器中,如果变量的地址被采用,那么   变量是用于在堆上分配的候选。但是,基本的   转义分析可以识别某些情况,而这些变量则不会   过了函数的返回,可以驻留在堆栈上。

编译器和垃圾收集器的行为严格依赖于实现,并且可能会在不同版本之间发生更改。 您不能事件证明您的开始语句始终为真:编译器可能决定根据您的函数的编写或调用方式应用进一步的优化。

答案 1 :(得分:2)

编译器执行escape analysis以确定变量是否可以在创建它的作用域之外使用,在这种情况下,它必须在堆上分配。如果编译器可以确保不会发生这种情况,它会在堆栈上分配变量。

但是,这是编译器的当前行为,但在规范中未提及,因此在将来的任何版本中都可能会更改。