【问题标题】:Interface can not call self method接口不能调用self方法
【发布时间】:2019-03-17 09:46:25
【问题描述】:

我定义了两个函数。当我将指针传递给它时,我无法获得定义的方法。这是为什么呢?

type Visitor interface {
    work()
}

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


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

错误:

v.work undefined (type *Visitor 是指向接口的指针,不是 接口)

有人知道为什么吗

【问题讨论】:

  • error msg: v.work undefined (type *Visitor is pointer to interface, not interface)

标签: pointers go methods interface


【解决方案1】:
func test(v *Visitor)  {
    v.work() // error
}

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

当使用非指针时,值v(或者更确切地说是它的类型)有一个方法work(),所以你可以调用它:

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

这里v.work() 有效,因为vVisitor 类型,它是一个接口,它包含方法work()

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

一个类型可能有一个与之关联的方法集interface type 的方法集是它的接口。任何 other 类型 T 的方法集由所有声明为接收器类型 Tmethods 组成。 对应的pointer type*T的方法集是所有用receiver*TT声明的方法集(即它还包含T的方法集)。 更多规则适用于包含嵌入字段的结构,如struct types 部分所述。任何其他类型都有一个空方法集。在一个方法集中,每个方法必须有一个uniqueblankmethod name

不同的是你尝试了相同的接口类型,这是行不通的。它适用于具体(非接口)类型。教训是永远不要使用指向接口的指针,除非你能解释为什么需要它(它很少需要)。

【讨论】:

    【解决方案2】:

    正如错误明确指出的那样:

    v.work undefined (type *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 上的工作代码

    【讨论】:

    • 不,这会导致不同的错误。您正在混淆与实现接口的类型相关的指针与指向接口类型的指针。
    • @nos First 在 golang 中你永远不应该创建指向接口的指针。
    • 当然不是,但这就是 OP 所做的,这就是问题所在。
    • @nos OP 出现错误,因为原因是方法集。他在指针类型的v接口上调用work方法。
    • @nos 如果你有什么我可以学习的,请与我分享。我喜欢从错误中吸取教训。
    猜你喜欢
    • 2013-11-08
    • 2023-04-03
    • 1970-01-01
    • 2018-05-06
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2018-08-23
    • 2021-04-08
    相关资源
    最近更新 更多