接口不能调用自我方法

时间:2018-10-12 07:53:09

标签: pointers go methods interface

我定义了两个功能。当我传递一个指向它的指针时,我无法获得已定义的方法。为什么会这样?

type Visitor interface {
    work()
}

func test(v *Visitor)  {
    v.work() // error
}


func test1(v Visitor)  {
    v.work() // ok
}

错误:

  

未定义v.work(类型* Visitor是指向接口的指针,不是   界面)

有人知道为什么,

2 个答案:

答案 0 :(得分:3)

func test(v *Visitor)  {
    v.work() // error
}

v.work()应该是方法调用。但是v的类型为*Visitor,它是指向接口的指针。 指向接口的指针有0个方法,它没有实现任何东西(空接口interface{}除外)。

使用非指针时,值v(或更确切地说,其类型)具有方法work(),因此您可以调用它:

func test(v Visitor)  {
    v.work() // ok
}

v.work()在这里起作用,因为v的类型为Visitor,它是一个接口,并且包含方法work()

可能令人困惑的是,如果将方法添加到(非指针,非接口)具体类型中,则相应的指针类型也将具有该方法,并且可以调用该方法。这是在Spec: Method sets:

  

类型可能具有与之关联的方法集interface type的方法集是其接口。任何 other 类型的T方法集都包含所有以接收者类型T声明的methods相应的pointer type *T的方法集是用接收者*TT声明的所有方法的集合(也就是说,它还包含T进一步的规则适用于包含嵌入式字段的结构,如struct types一节所述。其他任何类型的方法集都为空。在方法集中,每个方法必须具有uniqueblank method name

区别在于您对接口类型尝试了相同的操作,这是行不通的。它适用于具体(非接口)类型。教训是永远不要使用指向接口的指针,除非您可以推理为什么需要它(很少需要它)。

答案 1 :(得分:-2)

错误明确指出:

  

未定义v.work(类型* Visitor是指向接口的指针,不是   界面)

这是因为work()函数是在指向接收方的指针上调用但在值上定义的。

type Visitor interface {
    work()
}

但是在第二种情况下,当您遇到错误时,您正在传递指针类型的接收器。

在Golang规范Method sets中,定义为:

  

类型可能具有与之关联的方法集。一个方法集   接口类型是它的接口。任何其他类型T的方法集   包含所有以接收者类型T声明的方法。方法集   指针类型* T的所有方法的集合   用接收者* T或T声明(也就是说,它还包含方法   T集)。进一步的规则适用于包含嵌入式字段的结构,   如结构类型部分所述。任何其他类型都有   空方法集。在方法集中,每个方法必须具有唯一的   非空白的方法名称。

您可以采用的一种方法是使用可以在其上调用work()方法的结构来实现接口。

package main

import "fmt"

type Visitor struct{}

type Visit interface {
    work()
}

func test(v Visit)  {
    v.work() // error
    fmt.Printf("%+v", v)
}

func (v *Visitor) work(){}


func main(){
       v := Visitor{}
       test(&v)
}

Go playground上的工作代码