go語言的一些吐槽

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

相關文章
相關標籤/搜索