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接口,