有一个像这样的简单结构:
type Event struct {
Id int
Name string
}
这两种初始化方法有什么区别?
e1 := Event{Id: 1, Name: "event 1"}
e2 := &Event{Id: 2, Name: "event 2"}
为什么我会使用这些初始化方法中的任何一种?
由于
答案 0 :(得分:18)
第一种方法
e1 := Event{Id: 1, Name: "event 1"}
将变量e1
初始化为类型Event
的值。第二个
e2 := &Event{Id: 1, Name: "event1"}
正在初始化e2
作为指向类型Event
的值的指针正如您在注释中所述,在给定类型的值上定义的方法集是该子集的一个子集。在指向该类型值的指针上定义的方法集。这意味着如果您有方法
func (e Event) GetName() string {
return e.Name
}
然后e1
和e2
都可以调用此方法,但如果您有其他方法,请说:
func (e *Event) ChangeName(s string) {
e.Name = s
}
然后 e1
无法使用ChangeName
方法,而e2
则为。
这个(e1
无法使用ChangeName
方法,而e2
则不是这种情况(尽管可能是在撰写本文时)这个帮助),感谢@DannyChen提出这个问题,感谢@GilbertNwaiwu在下面的评论中进行测试和发布。
(为了解决上面的罢工部分:在结构类型上定义的方法集包括为类型定义的方法和指向类型的指针。
相反,Go现在自动取消引用方法的参数,这样如果方法接收到一个指针,Go就会调用指向该结构的指针的方法,如果方法收到一个值,则Go会调用该方法的值该结构指出。在这一点上,我更新这个答案的尝试可能会遗漏一些重要的语义,所以如果有人想要纠正这个或澄清随意添加一个指向更全面的答案的评论。这里有一些来自go操场的说明这个问题:https://play.golang.org/p/JcD0izXZGz。
在某种程度上,指针和值如何作为函数定义的方法的参数的这种变化影响了下面的话语的某些方面,但是我将保留其余的未经编辑的,除非有人鼓励我更新它,因为它似乎更多或在通过值与指针传递的语言的一般语义的上下文中不太正确。)
关于指针和值之间的区别,这个例子是说明性的,因为Go中通常使用指针来允许你改变变量所指向的值(但是有很多理由可以使用指针!对于典型用途,这通常是一个可靠的假设)。因此,如果您将ChangeName
定义为:
func (e Event) ChangeName(s string) {
e.Name = s
}
如果在值接收器上调用此函数将不会非常有用,因为值(不是指针)将不会保留对它们进行的更改(如果它们被传递到函数中)。这与围绕如何分配和传递变量的语言设计领域有关:What's the difference between passing by reference vs. passing by value?
您可以在Go Playground中的此示例中看到此内容:https://play.golang.org/p/j7yxvu3Fe6
答案 1 :(得分:3)
e1
的类型为Event
,e2
的类型为*Event
。初始化实际上是相同的(使用复合文字语法,也不确定该行话是Go还是C#或两者?)但是e2
使用'运算符地址'&
所以它返回一个指向该对象的指针而不是实例本身。