2016-09-28 146 views
7

有一個簡單的結構是這樣的: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另一種方式。 –

回答

10

第一種方法

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:剛剛測試過。不正確。兩者都可以使用方法 –

2

類型的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。謝謝你的解釋。我會試驗這個。 –