7
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结构的方法有什么区别?

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

4

2 回答 2

4

TL;DR没有区别1。变量是分配在栈上还是堆上取决于它的使用情况。

我对 Go 从各种初始化和调用案例生成的程序集进行了深入研究。v和之间生成的程序集b几乎相同。需要特别注意的d是,没有分配在栈1上。

决定一个变量是堆分配还是堆栈分配的是它的使用方式。将指针传递给仅将参数用作值的函数不会强制变量进行堆分配。但即使这不能保证,该规范允许任何 Go 编译器根据优化或代码生成的需要在堆栈和堆之间自由移动变量。Go抽象出堆与堆栈,就像 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)使用它会是正确的。我作弊回答了我认为你想问的问题。

于 2013-10-18T05:59:54.317 回答
3

In both cases, a Vertex struct is intialized in the same way.

The first expression returns value which is an initialized Vertex struct. With 6g's alignment rules, this means that you will get 8+8 = 16 bytes worth of Vertex struct, since every float64 is 8 bytes in size. The second expression allocates memory, enough for 8+8 = 16 bytes, uses it as a Vertex struct, initializes it and returns a pointer, which will be 4 or 8 bytes in size, depending on your architecture.

There are a number of differences in practice. The method sets of these two values, the Vertex struct and the *Vertex pointer, may be different. Depending on how often you need to pass around the Vertex struct, it might or might not be more efficient to pass a pointer to it. If you pass a Vertex struct to a function, the function gets a copy and your Vertex struct will never be modified. If you pass a *Vertex, your underlying Vertex might be changed. This might or might not be your intention :)

于 2013-10-16T21:41:15.863 回答