【问题标题】:Why can't the interface be implemented with pointer receivers为什么接口不能用指针接收器实现
【发布时间】:2015-08-04 21:16:22
【问题描述】:

我很困惑为什么编译失败:

不可能的类型断言: Faz 没有实现 Foo(Bar 方法有指针接收器)

如果我将 Faz.Bar 的接收器设为 Faz 值而不是 Faz 指针,那么它可以正常编译,但我认为拥有指针接收器总是更好,这样值就不会被复制?

package main

import (
    "log"
)

func main() {
    foo := New().(Faz)
    log.Println(foo)
}

type Foo interface {
    Bar() string
}

func New() Foo {
    return &Faz{}
}

type Faz struct {
}

func (f *Faz) Bar() string {
    return `Bar`
}

【问题讨论】:

  • 附带说明:@KerrekSB 引用的文章有助于我理解当 Go 抱怨“MyFoo 没有实现 Foo(Bar 方法有指针接收器)”时,它没有意味着您不能使用指针接收器。这意味着实现BarMyFoo 方法中的none 应该有指针接收器,或者all 必须有。这与@0xor1 遇到的问题不同,但其他人可能会发现这个问题,因为他们混合了他们的接收器类型(就像我一样)并且不理解他们得到的错误。

标签: pointers interface go


【解决方案1】:

因为它是*Faz 而不是Faz

func main() {
    foo := New().(*Faz)
    log.Println(foo)
}

【讨论】:

  • 它们可以是 *Faz 或 Faz,但它们都必须匹配。如果您打算 return Faz{} 或 *Faz 如果您打算 return &Faz{} ,则将它们全部定义。他们如何维护状态被认为是您基本上对用户隐藏的实现细节。
【解决方案2】:

我认为这个问题的答案需要对语法进行更回顾的方法,以及如何通过软件工程来实现它。 (请原谅过于简单化)


首先快速回顾一下types是什么?
它们只是顶部带有编译器逻辑的内存块。使arraystring 不同的是编译器允许我们对这些内存块执行的操作。 (深入思考,您可能会开始意识到strongly typeddynamically typed 语言之间的真正区别。)

接下来你需要意识到指针是它们自己的类型。
*variable 是与variable 不同的内存块(又名类型)。只是编译器始终假定*variable 的内容始终是声明右侧类型的内存块的地址以及它施加的其他限制/功能。

然后让我们回顾一下接口是什么。
伪科学定义:任何一等公民必须具有特定类型的一组要求。 转换为软件工程 - 任何具有与合同 (interface) 中描述的相关联的相同内存结构(回想 structure packing)的内存块(类型)都可以传递与合同中提到的类型名称一样。


现在你可能开始意识到,当你说

func (f *Faz) Bar() stringf 保存函数的内存块,其中f 的类型是指向Faz 的指针

所在区域

func (f Faz) Bar() stringf 的内存块,其中f 的类型是Faz

所以当你说*Faz 类型的变量满足契约时,你怎么能假设Faz 类型的变量在代码中符合接口类型的条件呢?选择谁满足你的合约,并且只有那个类型可以假设你代码中的接口类型。

【讨论】:

  • 我不同意你的解释,下面的程序工作(类型 *foo 满足 String() 为类型 foo 定义):package main import ("fmt" ) type foo struct{} func (f foo) String() string { return "111" } func main() { f := foo{} a := &foo{} var s fmt.Stringer s = as = f fmt.Println(f.String(), a .String(), s) }
猜你喜欢
  • 2019-11-23
  • 2016-11-05
  • 2018-01-20
  • 1970-01-01
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 2017-02-10
  • 2011-04-24
相关资源
最近更新 更多