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.

到底是对象实现了接口还是指向对象的指针实现了接口

先来看以下代码:

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赋值,而实际上运行这段代码将会报错:

# 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是一个指针.对代码稍作修改:

func main(){
    var a intf
    b := &st{val:10}
    a = b
    a.Show()
}

这次代码可以正确运行了,此时b应该是一个指向st的指针.这是说*st实现了intf接口?

现在我再把Show的定义改一下,main不变:

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

相关文章

程序目录结构 简单实现,用户登录后返回一个jwt的token,下次请求带上token请求用户信息接口并返回信息...
本篇博客的主要内容是用go写一个简单的Proof-of-Work共识机制,不涉及到网络通信环节,只是一个本地的简...
简介 默克尔树(MerkleTree)是一种典型的二叉树结构,其主要特点为: 最下面的叶节点包含存储数据或其...
接下来学习并发编程, 并发编程是go语言最有特色的地方, go对并发编程是原生支持. goroutine是go中最近本...
先普及一下, 什么是广度优先搜索 广度优先搜索类似于树的层次遍历。从图中的某一顶点出发,遍历每一个顶...
第一天: 接口的定义和实现 第二天: 一. go语言是面向接口编程. 在学习继承的时候说过, go语言只有封装,...