Go中方法调用和接口实现

本文探讨了Go语言中方法调用的区别,特别是值接收者与指针接收者。通过示例代码展示了接口实现时可能出现的问题,解释了为何*Gopher类型可以拥有Gopher类型实现的方法,而Gopher本身不被认为实现了接口中的所有方法。
方法调用

方法的接收者有两种:值接收者、指针接收者。这两种有什么区别呢?

来看下面这段代码,最后结果是什么呢?编译错误?

package main

import "fmt"

type Person struct {
    age int
}

func (p Person) howOld() int {
    return p.age
}

func (p *Person) growUp() {
    p.age += 1
}

func main() {
    // zhangsan 是值类型
    zhangsan := Person{age: 18}

    // 值类型 调用接收者也是值类型的方法
    fmt.Println(zhangsan.howOld())

    // 值类型 调用接收者是指针类型的方法
    zhangsan.growUp()
    fmt.Println(zhangsan.howOld())

    // ----------------------

    // stefno 是指针类型
    stefno := &Person{age: 100}

    // 指针类型 调用接收者是值类型的方法
    fmt.Println(stefno.howOld())

    // 指针类型 调用接收者也是指针类型的方法
    stefno.growUp()
    fmt.Println(stefno.howOld())
}

上面输出

18
19
100
101

结论

值接收者指针接收者
值类型调用者方法会使用调用者的一个副本,类似于“传值”使用值的引用来调用方法,上例中,qcrao.growUp() 实际上是 (&qcrao).growUp()
指针类型调用者指针被解引用为值,上例中,stefno.howOld() 实际上是 (*stefno).howOld()实际上也是“传值”,方法里的操作会影响到调用者,类似于指针传参,拷贝了一份指针
接口实现
package main

import "fmt"

type coder interface {
    code()
    debug()
}

type Gopher struct {
    language string
}

func (p Gopher) code() {
    fmt.Printf("I am coding %s language\n", p.language)
}

func (p *Gopher) debug() {
    fmt.Printf("I am debuging %s language\n", p.language)
}

func main() {
    var c coder = &Gopher{"Go"}
    c.code()
    c.debug()
}

coder 是一个接口类型,定义了 code() 和 debug() 两个函数

一个 Gopher 结构体实现了上面两个方法,注意一个是值接收者,一个是指针接收者

运行下,看结果:

I am coding Go language
I am debuging Go language

把调用者改为值调用者会怎么样呢

func main() {
    var c coder = Gopher{"Go"}
    c.code()
    c.debug()
}

运行下,报错:

src/main.go:23:6: cannot use Gopher literal (type Gopher) as type coder in assignment:
    Gopher does not implement coder (debug method has pointer receiver)

第一次是将 &Gopher 赋给了 coder;第二次则是将 Gopher 赋给了 coder。

第二次报错是说,Gopher 没有实现 debug 方法。有的同学可能会问 Gopher 不是可以调用 debug 方法吗,有实现呀。这里犯了一个理解上的错误,Gopher 可以调用 debug 方法是因为 Go 的语法糖。又有同学可能会问,那 *Gopher 也没有实现 code 方法,为什么可以将 &Gopher 赋给 coder。表面上看, *Gopher 类型也没有实现 code 方法,但是因为 Gopher 类型实现了 code 方法,所以让 *Gopher 类型自动拥有了 code 方法。

终于搞清楚了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值