struct的方法,若是receiver非指針,則調用這個方法沒法改變對象狀態,由於傳遞給方法的對象是原對象的一個拷貝,全部的改變都被做用在這個拷貝上而非原對象上.程序員
type st struct{ val uint32 } func (this st) Show(){ fmt.Printf("Show:%d\n",this.val) } func (this st) Increase(){ this.val += 1 fmt.Printf("Increase:%d\n",this.val) } func main(){ b := st{val:10} b.Increase() b.Show() }
輸出:網絡
Increase:11 Show:10
對於習慣了C++的程序員,總會認爲調用一個對象的非const方法是能夠改變那個對象的內部狀態.可是這種思惟若是延續到go中將會致使很難查找的bug.session
究竟是對象實現了接口仍是指向對象的指針實現了接口socket
先來看如下代碼:tcp
package main import "fmt" type intf interface{ Show() } type st struct{ val uint32 } func (this *st) Show(){ this.val += 1 fmt.Printf("%d\n",this.val) } func main(){ var a intf b := st{val:10} a = b a.Show() }
直觀上咱們認爲st實現了intf接口,因此能夠用b對a賦值,而實際上運行這段代碼將會報錯:ui
# command-line-arguments test/test.go:21: cannot use b (type st) as type intf in assignment: st does not implement intf (Show method has pointer receiver)
這段提示說st沒有實現intf接口,由於Show方法的receiver是一個指針.對代碼稍做修改:this
func main(){ var a intf b := &st{val:10} a = b a.Show() }
此次代碼能夠正確運行了,此時b應該是一個指向st的指針.這是說*st實現了intf接口?指針
如今我再把Show的定義改一下,main不變:code
func (this st) Show(){ this.val += 1 fmt.Printf("%d\n",this.val) }
代碼仍是能夠正確運行,同時若是把main恢復成下面這樣:對象
func main(){ var a intf b := st{val:10} a = b a.Show() }
代碼也是正確的.
也就是說,實現接口的方法時receiver是指針那麼只能用實現類型的指針對接口賦值,不然既能用實現類型的值也能用實現類型的指針對接口賦值.
最後再來看個例子,在一段網絡代碼中,我想將net.Conn轉換成net.TCPConn,以下代碼報錯:
tcpconn := this.Conn.(net.TCPConn) # kendynet-go/socket ./tcpsession.go:156: impossible type assertion: net.TCPConn does not implement net.Conn (Close method has pointer receiver) Makefile:2: recipe for target 'all' failed
正確的作法是:
tcpconn := this.Conn.(*net.TCPConn)
這是否證實了,是*net.TCPConn而不是net.TCPConn實現了net.Conn接口,