我为什么要使用&签署结构?

时间:2018-01-07 08:53:23

标签: go

在gotour中,有一节:struct literals。

package main

import "fmt"

type Vertex struct {
    X, Y int
}

var (
   v1 = Vertex{1, 2}  // has type Vertex
   v2 = Vertex{X: 1}  // Y:0 is implicit
   v3 = Vertex{}      // X:0 and Y:0
   p  = &Vertex{1, 2} // has type *Vertex
)

func main() {
   fmt.Println(v1, p, v2, v3)
}

带有&符号的结构与没有&的结构之间的区别是什么?我知道带有&符号的那些指向相同的参考,但为什么我应该使用它们而不是常规的?&/ p>

 var p = &Vertex{} // why should I use this
 var c = Vertex{} // over this

2 个答案:

答案 0 :(得分:4)

这些评论几乎说明了这一点:

   v1 = Vertex{1, 2}  // has type Vertex
   p  = &Vertex{1, 2} // has type *Vertex

与许多其他语言一样,& takes the address后面的标识符。当你想要一个指针而不是一个值时,这很有用。

如果您需要了解有关编程指针的更多信息,可以从this开始,甚至是wikipedia页。

答案 1 :(得分:2)

确实p&Vertex{})的类型为*Vertex,而cVertex{})的类型为Vertex

但是,我不认为该陈述真正回答了为什么一个选择另一个的问题。这就像在回答“为什么要在汽车上使用飞机”之类的问题时,例如“飞机有翼而汽车没有”。 (显然,我们都知道机翼是什么,但是您明白了。)

但是简单地说“去学习指针”也不会有很大帮助(尽管如此,尽管如此,我仍然认为这确实是一个好主意)。


您的选择基本上可以归结为以下内容。

  • 意识到&Vertex{}Vertex{}从根本上是以相同的方式初始化的。

    • 可能在底层内存分配方面存在一些差异(即堆栈与堆),但您实际上应该只让编译器担心这些细节
  • 哪个功能比另一个功能更有用和更有效取决于程序中它们的使用方式。

  • “我要指向结构(p)的指针,还是仅指向结构(c的指针?”

    • 请注意,您可以使用&运算符(例如&c)来获得指针;您可以使用*取消引用指针以获取值(例如*p
      • 因此,根据您选择的内容,您可能最终会做很多*p&c
      • 底线:创建将要使用的内容;如果您不需要一个指针,请不要使用它(从长远来看,这将有助于“优化”)。

  • 我应该使用Vertex{}还是&Vertex{}
    • 对于您的示例中给出的Vertex,我选择Vertex{}来获得一个简单的值对象。
    • 某些原因:
        示例中的
      • Vertex的大小很小。复制很便宜。
      • 简化了垃圾收集,编译器可以减轻垃圾的产生
      • 指针可能会变得棘手,并给程序员增加不必要的认知负担(即难以维护)
      • 如果您要进行并发操作(即不安全),指针就不是您想要的东西
      • Vertex确实不包含任何值得修改的内容(只需在需要时返回/创建一个新的Vertex)即可。
    • 您想要&Struct{}的某些原因
      • 如果Struct的成员正在缓存某些状态,该状态需要在原始对象本身内部进行更改。
      • Struct巨大,并且您已经进行了足够的性能分析,以确定复制成本很高。
        • 顺便说一句:您应该尽量减小struct的大小,这是一个好习惯。
      • 您发现自己是偶然制作副本(这有点麻烦):
         v := Struct{}
        v2 := v  // Copy happens
        
         v := &Struct{}
        v2 := v  // Only a pointer is copied