将结构初始化为指针或不作为指针

时间:2013-10-16 21:30:26

标签: go

type Vertex struct {
    X, Y float64
}

func main() {
    v := Vertex{3, 4}
    fmt.Println(v)

    d := &Vertex{3, 4}
    fmt.Println(d)
}

http://play.golang.org/p/XluyUHL2y7

这两种初始化Vertex结构的方法之间有什么区别?

我知道第二个是指针分配,但在实践中我看不出这个解决方案有什么不同。

2 个答案:

答案 0 :(得分:3)

TL; DR 1 没有区别。是否在堆栈或堆上分配变量取决于其用法。

我在程序集上做了deep dive Go从各种初始化和调用情况生成。在vb之间生成的程序集几乎相同。特别值得注意的是,d未在堆栈 1 上分配。

确定变量是堆分配还是分配堆栈的方法是使用它的方式。将指针传递给仅将参数用作值的函数将不会强制将变量分配给堆。但即使这样也无法保证,规范允许任何Go编译器根据需要在堆栈之间自由移动变量以进行优化或代码生成。转发abstracts away Heap vs Stack就像C / C ++抽象出RAM与寄存器一样。

http://play.golang.org/p/vJQvWPTGeR

type Vertex struct {
    X, Y float64
}

func PrintPointer(v *Vertex) {
    fmt.Println(v)
}

func PrintValue(v *Vertex) {
    fmt.Println(*v)
}

func main() {
    a := Vertex{3, 4} // not allocated
    PrintValue(&a)

    b := &Vertex{3, 4} // not allocated
    PrintValue(b)

    c := Vertex{3, 4} // allocated
    PrintPointer(&c)

    d := &Vertex{3, 4} // allocated
    PrintPointer(d)
}

1 :技术上不正确,但如果使用fmt.Println(*d)则会成立。我有点作弊回答了我认为你想问的问题。

答案 1 :(得分:2)

在这两种情况下,Vertex结构都以相同的方式初始化。

第一个表达式返回值,它是一个初始化的Vertex结构。使用6g的对齐规则,这意味着您将获得8 + 8 = 16字节的Vertex结构,因为每个float64的大小为8个字节。 第二个表达式分配内存,足够8 + 8 = 16个字节,将其用作Vertex结构,初始化它并返回一个指针,大小为4或8个字节,具体取决于您的体系结构。

在实践中存在许多差异。这两个值的方法集,Vertex结构和* V​​ertex指针可能不同。根据您需要传递Vertex结构的频率,将指针传递给它可能会或可能不会更有效。如果将Vertex结构传递给函数,该函数将获得一个副本,并且永远不会修改Vertex结构。如果传递*顶点,则可能会更改基础顶点。这可能是也可能不是你的意图:)