這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
剛入手golang,大概弄清楚了method在go裡的概念。
以下大部分為搬運過程重寫代碼。
method可以為一個type添加(聲明)一個方法,例如:
type Cat struct {}func (c Cat) Hwo() { fmt.Println("Miah!")}
即對Cat類型(結構體)添加Hwo方法,使其在叫喚的時候可以發出聲音。
這種添加方法的代碼錶現比java好很多(extend),也比python好(需重新聲明一個Class)。
按官方的spec可以對應到如上的例子的兩種聲明:
func (c Cat) Hwo()func (c *Cat) Hwo()
兩種有什麼區別呢?
package mainimport ( "fmt")type Cat struct { age int}func (c Cat) AddAge() { fmt.Println("add age!") fmt.Println(c.age + 10) c.age += 1}func (c *Cat) AddOneAge() { c.age += 1 fmt.Println("add one age!")}func main() { cat := &Cat{1} fmt.Println(cat) cat.AddAge() fmt.Println(cat) cat.AddOneAge() fmt.Println(cat)}
結果:
&{1}add age!11&{1}add one age!&{2}
修改cat聲明方式為
cat := Cat{1}
結果:
{1}add age!11{1}add one age!{2}
發生了什嗎?
1.cat變數是一個指標,可以用reflect.Typeof(cat)看出來;
2.(c Cat)添加的方法AddAge()被執行了,能擷取cat的值,但是未改變cat指標指向的記憶體區塊的值;
3.(c *Cat)添加的方法AddOneAge()被執行了,改變cat指標指向的記憶體區塊的值;
4.重新定義catb := Cat{1},似乎catb非指標,但是還是一樣的結果(除了變數部分)。
如何解讀?
1.無論是將一個變數聲明為指標還是非指標,go在method上對待它們的態度都是一致的;
2.聲明method時,傳入(c *Cat)的聲明方式才能修改new出來的對象(cat :=),因為method的處理對象是一個Cat類型的指標。
3.在聲明變數時,建議聲明為指標對象cat := &Cat{1},這樣做有好處
a.傳遞指標有卓有成效的,特別是傳遞大型變數時
b.大部分科學的代碼是傳遞指標,為了代碼的一致性最好都用指標
詳見Reference.3
題外話,這裡有個例子可以闡明一個狀況
對於interface來說,識別method時會辨別(c Cat)及(c *Cat)的區別:
http://play.golang.org/p/-g44WHg_uT
Reference
1.http://nathanleclaire.com/blog/2014/08/09/dont-get-bitten-by-pointer-vs-non-pointer-method-receivers-in-golang/
2.http://golang.org/ref/spec#Method_declarations
3.http://golang.org/doc/faq#methods_on_values_or_pointers