我定义了两个功能。当我传递一个指向它的指针时,我无法获得已定义的方法。为什么会这样?
type Visitor interface {
work()
}
func test(v *Visitor) {
v.work() // error
}
func test1(v Visitor) {
v.work() // ok
}
错误:
未定义v.work(类型* Visitor是指向接口的指针,不是 界面)
有人知道为什么,
答案 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
的方法集是用接收者*T
或T
声明的所有方法的集合(也就是说,它还包含T
。进一步的规则适用于包含嵌入式字段的结构,如struct types一节所述。其他任何类型的方法集都为空。在方法集中,每个方法必须具有unique非blank 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上的工作代码