2014-01-10 56 views
1

爲什麼我不需要將PrintValue()定義爲指針接收器(* One)以便能夠打印「hello」?作爲指針的方法接收器之間的區別

package main 
import "fmt" 


type One struct{ 
    a string 
} 
func (o *One)AssignValue(){ 
    o.a = "hello" 
} 
func (o One)PrintValue(){ 
    fmt.Println(o.a) 
} 

func main() { 
    one := One{} 
    one.AssignValue() 
    one.PrintValue() 
} 

回答

0

因爲one已經是One類型。實例化語法

t := One{} 

One創建類型的而形式

p := &One{} 

創建指針One類型的值

這意味着,沒有什麼是調用t.PrintValue,當作爲接收器類型(One)已經是相同的t類型(One一樣)來完成。

當調用p.PrintValue編譯器,因爲接收器類型(One)不等於的p*One)的類型的可尋址可變自動轉換到它的指針的形式。所以表達式

p.PrintValue() 

轉換爲

(*p).PrintValue() 

主叫t.AssignValue當作爲這種方法有一個指針接收器但我們提供值還有一個轉換必要的。如果可能,這也由編譯器自動完成。

the spec on calls

一個方法調用x.m()是有效的,如果的X(的類型)的方法集包含m和參數列表可以被分配到m的參數列表。 如果x是可尋址的並& X的方法集包含米,XM()是簡寫(& X).M()

這意味着表達

t.AssignValue() 

轉換爲

(&t).AssignValue() 

請注意,這並非總是可行。例如,當從一個函數返回一個值時:

func NewOne(s string) One { return One{s} } 

NewOne("foo").AssignValue() // Not possible 

x := NewOne("foo") 
x.AssignValue() // Possible, automatically converted 
+0

所以這是「幕後魔法」......如果你問我,有點混亂。 –

+0

但是,如果AssignValue()未被定義爲指針接收者,則PrintValue()會打印一個空字符串。那爲什麼呢? –

+0

因爲那麼''AssignValue'中的'o'被複制並且您的修改僅在副本上完成。 – nemo