Go语言方法绑定,很奇怪的现象

首先看一段代码:


// typeAssert project main.go
package main

import (
    "fmt"
)

type Student struct {
    name string
}

type Ione interface {
    getName() string
}

type Itwo interface {
    getName() string
    setName(name string)
}

func (s Student) getName() string {
    return s.name
}
func (s *Student) setName(name string) {
    s.name = name
}

func main() {
    // 申明一个接口对象
    var i Ione
    // 定义一个Student结构体变量
    s := Student{}
    // 向上赋值
    i = s
    _, ok := i.(Student)
    fmt.Println(ok)
}

上面的代码很简单,诸位可以复制运行。
问题:当我把函数

func (s Student) getName() string {
    return s.name
}

的receiver改成指针类型,即写成如下:

func (s *Student) getName() string {
    return s.name
}

编译马上报错。很奇怪这是为什么????

阅读 5.9k
2 个回答

自己在工作的过程当中也写了半年的go语言,今天一看这个问题突然懵逼了,所以去学习了一下文档。在此回馈题主。

type A struct {
    name string
}

func (a *A)hello(){}
func (a A)word(){}

首先我们定义上面的一个类型A。假设现在我们想定义一个对象并且调用hello方法的时候,可以采取以下两种形式:

var a A
a.hello()
(&a).hello()

正常来讲,因为hello这个函数的reciver是指针类型,那么我们理所应当应该使用A对象的指针来调用,也就是第二种形式。那么为何第一种也可以呢?因为go在背后帮我们做了转换。实际上,A和*A本身是两种不同的类型,当我们使用a.hello()的时候,go会自动帮我们转换成(&a).hello()的形式。

golang中没有像C++语言中this这种隐含的设定,reciver看起来和this差不多,实际上它也是其所在函数的一个参数。如上面例子中的hello方法,功能上是等价于下面这个函数的。

hello(a *A)

所以我们可以以另一种形式来调用hello

(*A).hello(&a)

hello是为*A类型定义的一个函数,word是为A类型定义的一个函数。
如果现在有一个interface

type Ione interface{
    hello()
}

Ione类型的对象只能被复制为A的指针类型的值,因为一个有特定method的inteface只能被赋值一个实现了该interface内所有方法的对象。而且,根据上面的代码我们可以看出来,*A类型才实现了hello方法,A类型只实现了word方法,所以,将A类型的对象直接赋值给Ione类型的对象是不能通过编译的。

如果我说的还不理解,可以看下官网的文档
https://golang.org/ref/spec#M...

i变量要求的是s的指针,而不是s的本体
i = &s 就好了


    func main() {
        // 申明一个接口对象
        var i Ione
        // 定义一个Student结构体变量
        s := Student{}
        // 向上赋值
        i = &s
        _, ok := i.(*Student)
        fmt.Println(ok)
    }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题