2 回答
TA贡献1848条经验 获得超2个赞
func test(v *Visitor) { v.work() // error }
v.work()
应该是一个方法调用。但是v
是 type *Visitor
,一个指向接口的指针。指向接口的指针有 0 个方法,它不实现任何东西(空接口除外interface{}
)。
使用非指针时,值v
(或更确切地说它的类型)有一个 method work()
,因此您可以调用它:
func test(v Visitor) { v.work() // ok }
这里v.work()
有效,因为v
is 是一个接口类型Visitor
,它包含方法work()
。
可能令人困惑的是,如果您将方法添加到(非指针,非接口)具体类型,则相应的指针类型也将具有该方法,您可以调用它。这是在规范中:方法集:
一个类型可能有一个与之关联的方法集。接口类型的方法集就是它的接口。任何其他类型的方法集
T
由所有用接收者类型声明的方法T
组成。对应指针类型的方法集是所有用receiver or声明的方法的集合(即也包含了 的方法集)。*T
*T
T
T
进一步的规则适用于包含嵌入式字段的结构,如结构类型部分所述。任何其他类型都有一个空方法集。在一个方法集中,每个方法必须有一个唯一的非空白 方法名称。
不同之处在于您对接口类型进行了相同的尝试,但这是行不通的。它适用于具体(非接口)类型。教训是永远不要使用指向接口的指针,除非你能解释为什么需要它(很少需要)。
TA贡献1887条经验 获得超5个赞
正如错误明确指出的那样:
v.work 未定义(类型 *Visitor 是指向接口的指针,而不是接口)
这是因为 work() 函数是在指向接收器的指针上调用但在值上定义的。
type Visitor interface { work() }
但是在第二种情况下你正在传递指针类型的接收器,你会得到一个错误。
在 Golang 规范中,方法集定义为:
一个类型可能有一个与之关联的方法集。接口类型的方法集就是它的接口。任何其他类型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)
}
- 2 回答
- 0 关注
- 119 浏览
添加回答
举报