Golang Receiver 和 函数参数的区别

我们来比较下面两种方式

func (d *duck) quack() { // receiver
     // do something
}
func quack(d *duck) { // funciton argument
    // do something
}

如果我们习惯于对象的话,可能会熟悉 d.quack() 觉得更加直观,可读性也更好。但是本质区别是什么呢?

最重要的本质是:receiver 和 interface 相关,函数可以被动态调用。如果你不使用interface,那么无所谓使用哪个,使用 receiver 唯一的优势在于语法糖。

但是,假如测试时候,需要想对 quack() 做存根函数。那么下面的代码是不能实现的,因为方法和类型是强一致的,不能被改变。Golang 没有一个方法变量。

type duck struct{}

func (d *duck) quack() {
     // do something
}

// the function we are testing:
func testme(d *duck) {
    d.quack() // cannot be stubbed
}

但是,如果你使用了函数参数,那么事情就变得很容易:

type duck struct{}

var quack = func(d *duck) {
     // do something
}

// the function we are testing:
func foo(d *duck) {
    quack(d)
}

使用函数参数的方式,就将另外一个函数赋值给quack了,那么存根也容易实现,例如:quack = func(d *duck) { // do something else }

或者可以使用 interface

type quacker interface {
    quack()
}

type duck struct{}

var func (d *duck) quack() { // satisfies quacker
     // do something
}

// the function we are testing:
func foo(d quacker) {
    d.quack()
}

如果我们这里想测试 foo,那么我们提供一个不同的quacker即可。

结论:
只有如果有必要使用interface 时候,receiver的使用也是有意义的,否则实际使用中,使用quack(d) 要比 d.quack() 更好一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值