为什么我应该在结构上使用 & 符号?

Tom*_*omy 14 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)
}
Run Code Online (Sandbox Code Playgroud)

带有 & 符号的结构体和不带符号的结构体有什么区别?我知道带有 & 符号的那些指向相同的引用,但我为什么要在常规引用上使用它们呢?

 var p = &Vertex{} // why should I use this
 var c = Vertex{} // over this
Run Code Online (Sandbox Code Playgroud)

Yen*_*ang 29

确实,p( &Vertex{}) 有类型*Vertexc( Vertex{}) 有类型Vertex

但是,我不相信这种说法真的回答了为什么一个人会选择一个而不是另一个的问题。这有点像回答“为什么使用飞机而不是汽车”的问题,比如“飞机有翼,汽车没有”。(显然我们都知道翅膀是什么,但你懂的)。

但简单地说“去学习指针”也不会很有帮助(尽管我认为这是一个非常好的主意)。


你如何选择基本上归结为以下几点。

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

    • 可能存在一些低级内存分配差异(即堆栈与堆),但您真的应该让编译器担心这些细节
  • 是什么使一个比另一个更有用和更高效取决于它们在程序中的使用方式

  • “我想要一个指向 struct ( p)的指针,还是只是 struct ( c)?”

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

  • 我应该使用Vertex{}还是&Vertex{}
    • 对于Vertex您的示例中给出的内容,我会选择Vertex{}获取一个简单的值对象。
    • 一些原因:
      • Vertex在这个例子中,它的大小非常小。抄袭很便宜。
      • 垃圾收集被简化,垃圾创建可能会被编译器减轻
      • 指针可能会变得棘手,并给程序员增加不必要的认知负担(即变得更难维护)
      • 如果您遇到并发(即它是不安全的),则指针不是您想要的东西
      • Vertex并不真正包含任何值得改变的东西(只需Vertex在需要时返回/创建一个新的)。
    • 你想要的一些原因 &Struct{}
      • 如果Struct有一个成员缓存一些需要在原始对象本身内部更改的状态。
      • Struct巨大的,并且您已经进行了足够的分析来确定复制的成本是巨大的。
        • 顺便说一句:你应该尽量保持你struct的小,这只是一个很好的做法。
      • 你发现自己不小心复制了(这有点牵强):
         v := Struct{}
        v2 := v  // Copy happens
        
        Run Code Online (Sandbox Code Playgroud)
         v := &Struct{}
        v2 := v  // Only a pointer is copied
        
        Run Code Online (Sandbox Code Playgroud)


Mar*_*arc 4

评论几乎已经说明了这一点:

   v1 = Vertex{1, 2}  // has type Vertex
   p  = &Vertex{1, 2} // has type *Vertex
Run Code Online (Sandbox Code Playgroud)

与许多其他语言一样,采用其后的标识符的& 地址。当您需要指针而不是值时,这很有用。

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