英文:
Golang: The differences between these two ways of initializing struct
问题
我正在为您翻译以下内容:
我想知道在Go语言中初始化结构体的这两种方式有什么区别。第二种方式是否会给你一个存储结构体地址的指针?但是,如果我们想要更改字段变量,它们具有相同的语法,那它们有什么不同之处?
显然,我可以对指针进行解引用。但它们是否具有不同的功能?在什么情况下我会更喜欢其中一种方式?
b := Student{Name:"Bob"}
pb := &Student{Name:"Bob", Age:8}
英文:
I am wondering what the differences are between those two ways of initializing a struct in Go. Does the second one give you a pointer storing the address of the struct? But they have the same syntax if we want to change the field variables, so how are they different?
I can de-reference the pointer, apparently. But do they have different functionalities? In what scenario would I prefer one over the other?
b := Student{Name:"Bob"}
pb := &Student{Name:"Bob", Age:8,}
答案1
得分: 0
它们只在本地变量的类型上有所不同。优先选择哪个取决于在函数的其余部分如何使用该变量。如果你总是将它传递(即在赋值的右侧使用它,作为函数调用的参数或返回值)作为指针,可以使用pb := &Student{...}
的形式。如果你打算创建它的(浅层)副本,b := Student{...}
的形式可能更方便。然而,这纯粹是基于键入pb
比键入&b
更容易,键入b
比键入*pb
更容易的事实。如果你在所有地方都应用这些替换(除了在字段访问的上下文中,那里允许但不是必需的,见下文),它们是完全可互换的。
如果你想能够将持有结构体(指针)的变量设置为nil
,显然要使用指针。但这也可以通过引入一个新的指针类型的变量,并将其设置为nil
或&b
来解决。
Go中的某些类型无法复制(这通常通过在结构体中嵌入一个[0]sync.Mutex
字段来实现,该字段不占用空间,但会触发编译器的“互斥锁复制”错误)。一个例子是protobuf结构体。对于这些类型,几乎总是优先使用指针形式;然而,这并非是必需的,因为通过b := Student{...}
进行的初始化不是复制。
在访问结构体字段时,Go允许透明地解引用。b.Name
、(&b).Name
、pb.Name
、(*pb).Name
都可以工作且等效。但请注意,透明解引用仅适用于一级,(&pb).Name
将导致编译器错误。
英文:
They only differ in what the type of the local variable is. Whether to prefer one over the other depends entirely on how you would use that variable in the remainder of the function's body. If you are always passing it around (meaning use it on the right-hand side of an assignment, as an argument to a function call, or returning it) as a pointer, use the pb := &Student{...}
form. If you intend to create (shallow) copies of it, the b := Student{...}
form might be more convenient. This is however purely based on the fact that typing pb
is easier than &b
, and that typing b
is easier than *pb
. If you apply these substitutions everywhere (except for in the context of field accesses, where it is allowed but not mandatory, see below), they are completely interchangeable.
If you want to be able to set the variable holding the struct (pointer) to nil
, use a pointer, obviously. But this can also be solved by introducing a new, pointer-typed variable and setting that to either nil
or &b
.
Some types in Go cannot be copied (this is typically accomplished by embedding a [0]sync.Mutex
field in the struct, which takes up no space but triggers the "mutex copy" error of the compiler). An example would be protobuf structs. For these, it is almost always preferable to use the pointer form; however, this is not required, as the initialization via b := Student{...}
is not a copy.
Go allows transparently dereferencing when accessing struct fields. b.Name
, (&b).Name
, pb.Name
, (*pb).Name
all work and are equivalent. Note however that transparent dereferencing only works over one level, (&pb).Name
will result in a compiler error.
答案2
得分: 0
复合字面量在初始化Age
字段方面有所不同。第一个示例将字段设置为零值。第二个示例将字段设置为数字8。否则,结构值的初始化是相同的。
接下来发生的事情是关键差异所在。第一个示例将值分配给名为b
的变量。第二个示例将值分配给一个匿名变量;获取变量的地址;并将结果分配给名为pb
的变量。
b
的类型是结构类型,pb
的类型是指向结构类型的指针。
请参阅I don't understand when to use pointers on go以了解为什么可能需要使用指针的讨论。
英文:
The composite literals differ in the initialization of the Age
field. The first sets the field to the zero value. The second sets the field to the number 8. Otherwise, the initialization of the struct values is identical.
What happens next is where the key difference lies. The first example assigns the value to a variable named b
. The second example takes assigns the value to an anonymous variable; takes the address of the variable; and assigns the result to a variable named pb
.
The type of b
is the struct type and the type of pb
is a pointer to the struct type.
See I don't understand when to use pointers on go to see a discussion on why one might want to use a pointer.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论