Golang结构初始化

问题描述:

有一个简单的结构是这样的:Golang结构初始化

type Event struct { 
    Id   int 
    Name  string 
} 

的是这两个初始化方法之间的区别?

e1 := Event{Id: 1, Name: "event 1"} 
e2 := &Event{Id: 2, Name: "event 2"} 

任何为什么我会使用这些初始化方法?

由于

+3

这些类型的构建的是围棋和非常基本的东西在Tour of Go(https://tour.golang.org/)中很好地解释了这一点。再次通过巡回演出的方式如何? – Volker

+1

旅行中有一点不明确。初始化一个结构时,获取指针与实例本身是有区别的。何时以及为什么我会使用一种方式VS另一种方式。 –

第一种方法

e1 := Event{Id: 1, Name: "event 1"} 

正在初始化变量e1Event类型的值。第二

e2 := &Event{Id: 1, Name: "event1"} 

正在初始化e2作为指针以当您在注释中规定,在一个给定类型的值定义的组的方法被定义Event的一套方法的一个子集类型的值在一个指向该类型值的指针上。这意味着,如果你有一个方法

func (e Event) GetName() string { 
    return e.Name 
} 

那么这两个e1e2可以调用此方法,但如果你有另一种方法,说:

func (e *Event) ChangeName(s string) { 
    e.Name = s 
} 

然后e1不能使用ChangeName方法,而e2是。

这(e1不能使用ChangeName方法,而e2是)事实并非如此(虽然它可能已经在写这个帮助的时候),这要归功于@DannyChen对于提出这个问题和@GilbertNwaiwu在下面的评论中进行测试和发布。

(为了解决上面的删除线出部分:该组上的结构类型定义的方法包括为类型和指针的类型中定义的方法

相反,转到现在自动解除引用的参数一个方法,所以如果一个方法接收到一个指针,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?

你可以看到这个在这个例子中去游乐场:https://play.golang.org/p/j7yxvu3Fe6

+0

很好的解释,谢谢 –

+0

“然后e1不能使用ChangeName方法,而e2是。”这个结论是否正确? –

+0

@DannyChen:刚刚测试过。不正确。两者都可以使用方法 –

类型的e1Evente2类型是*Event。初始化实际上是相同的(使用复合文字语法,也不确定该术语是Go还是C#或两者?),但使用e2您使用'address of operator'&,因此它返回指向该对象的指针而不是实例本身。

+0

e1.SomeMethod()vs * e2.SomeMethod本质上是一样的吗?如果我没有弄错,Go会去做(* e1).SomeMethod()。 –

+0

@sheldon_cooper不完全是,它们是不同的类型。如果我有一个像'func(e * Event)Test()'这样的方法并试图执行'e1.Test()',我会得到一个编译器错误。我可以执行'ep:=&e1',然后执行'ep.Test()',或者你可以执行内联或其他任何操作,但必须获取指针才能调用由指针定义的方法作为接收者。基本上,当调用方法时,不会为你按摩或强制类型。它必须匹配方法定义中的内容。你可以很容易地将值转换为指针或指向值的指针。 – evanmcdonnal

+0

是的,我明白参考价值接收器类型之间的差异。我在规范中提到“如果x的(类型)的方法集合包含m,并且参数列表可以分配给m的参数列表,则方法调用xm()是有效的。如果x是可寻址的,并且&x的方法set包含m,xm()是(&x).m()的简写:“规范的URL是:https://golang.org/ref/spec#Calls。谢谢你的解释。我会试验这个。 –