当前位置: 首页 > 面试题库 >

X不实现Y(…方法具有指针接收器)

吴高畅
2023-03-14
问题内容

已关闭 。这个问题需要细节或说明。它当前不接受答案。

想改善这个问题吗? 添加详细信息并通过编辑此帖子来澄清问题。

3个月前关闭。

改善这个问题

关于“ X不能实现Y(…方法具有指针接收器) ”的事情已经有一些问答,但是对我来说,他们似乎在谈论不同的事情,而不适用于我的具体情况。

因此,我没有使问题变得非常具体,而是使之变得笼统和抽象-似乎有几种不同的情况可以使此错误发生,请有人总结一下吗?

即,如何避免该问题,如果发生,可能性是什么?谢谢。


问题答案:

当您尝试将 具体 类型分配或传递(或转换)为接口类型时,会出现此编译时错误。并且类型本身不实现接口,仅实现 指向type指针

让我们来看一个例子:

type Stringer interface {
    String() string
}

type MyType struct {
    value string
}

func (m *MyType) String() string { return m.value }

Stringer接口类型只有一个方法:String()。接口值中存储的任何值都Stringer必须具有此方法。我们还创建了一个MyType,并创建了一个MyType.String()带有
指针
接收器的方法。这意味着String()方法在方法集合的的*MyType类型,但不是在的MyType

当我们尝试将值MyType赋给type的变量时Stringer,我们得到了相关的错误:

m := MyType{value: "something"}

var s Stringer
s = m // cannot use m (type MyType) as type Stringer in assignment:
      //   MyType does not implement Stringer (String method has pointer receiver)

但是,如果我们尝试将type的值分配*MyTypeStringer

s = &m
fmt.Println(s)

我们得到了预期的结果(在Go Playground上尝试):

something

因此,获取此编译时错误的要求:

  • 分配(或传递或转换)的 非指针 具体类型的值
  • 分配给(或传递给或转换为)的接口类型
  • 具体类型具有接口的必需方法,但带有 指针接收器

解决此问题的可能性:

  • 必须使用指向该值的指针,该指针的方法集将包括带有指针接收器的方法
  • 否则必须将接收者类型更改 为非指针 ,因此非指针具体类型的方法集也将包含方法(并因此满足接口)。这可能是可行的,也可能是不可行的,就像该方法必须修改该值一样,非指针接收器也不是一种选择。

结构和嵌入

使用结构和嵌入时,实现接口的通常不是“您”(提供方法实现),而是嵌入到中的类型struct。像这个例子一样:

type MyType2 struct {
    MyType
}

m := MyType{value: "something"}
m2 := MyType2{MyType: m}

var s Stringer
s = m2 // Compile-time error again

再次出现编译时错误,因为的方法集MyType2不包含String()Embedded
MyType的方法,仅包含的方法集*MyType2,因此以下工作(在Go
Playground上尝试):

var s Stringer
s = &m2

如果我们*MyType仅嵌入并使用 非指针 ,也可以使其工作MyType2(在Go
Playground上尝试):

type MyType2 struct {
    *MyType
}

m := MyType{value: "something"}
m2 := MyType2{MyType: &m}

var s Stringer
s = m2

另外,无论我们嵌入什么(MyType*MyType),如果我们使用指针*MyType2,它将始终有效(在Go
Playground上尝试):

type MyType2 struct {
    *MyType
}

m := MyType{value: "something"}
m2 := MyType2{MyType: &m}

var s Stringer
s = &m2

规范中的相关部分(来自“ 结构类型”部分):

给定一个结构类型S和一个名为的类型T,在该方法的方法集中包括了提升的方法,如下所示:

  • 如果S包含匿名字段T,则S和的方法集*S都将包含带有接收器的升级方法T。方法集*S还包括带有接收方的提升方法*T
  • 如果S包含匿名字段*T,则S和的方法集*S都将包含带有接收者T或的升级方法*T

所以换句话说:如果我们嵌入一个非指针类型,则非指针嵌入器的方法集只能获取带有非指针接收器的方法(来自嵌入式类型)。

如果我们嵌入一个指针类型,则非指针嵌入器的方法集将获得同时具有指针和非指针接收器的方法(来自嵌入式类型)。

如果我们使用指向嵌入器的指针值,则不管嵌入的类型是否为指针,指向嵌入器的指针的方法集总是获取带有指针和非指针接收器的方法(来自嵌入类型)。

注意:

有一种非常相似的情况,即当您有一个包装了值的接口值MyType,并尝试从中键入assert另一个接口值时Stringer。在这种情况下,由于上述原因该断言将不成立,但是我们会得到一个稍微不同的运行时错误:

m := MyType{value: "something"}

var i interface{} = m
fmt.Println(i.(Stringer))

运行时恐慌(在Go Playground上尝试):

panic: interface conversion: main.MyType is not main.Stringer:
    missing method String

尝试转换而不是类型断言,我们得到了我们正在谈论的编译时错误:

m := MyType{value: "something"}

fmt.Println(Stringer(m))


 类似资料:
  • 问题内容: 我有这个示例代码 无法正常工作,因为其接收器不是指针类型。 如果我将方法更改为指针接收器,那么我希望它可以正常工作,如下所示: 编译会导致以下错误: 如何在不创建副本的情况下使接口 和 方法实现实际实例的值? 这是一个可入侵的代码段:https : //play.golang.org/p/ghW0mk0IuU 问题答案: 您指向结构的指针应实现该接口。这样,您可以修改其字段。 查看我如

  • 问题内容: 在Golang中工作,正在尝试使用接口将使用相似方法的一组结构归为一组。简而言之,我有这个: 然后,应该用作接口的结构: 我想念什么?还是我做错了什么? 问题答案: 如果您的接口这样声明: 然后,任何实现a的类型都将满足该接口。 在您的情况下,然后创建此方法: 这意味着类型满足接口。 但是..注意那里。没有实现该接口,而是由谁来实现。 因此,在尝试为接口变量分配类型时,请确保使用指针而

  • 问题内容: 我很难理解为什么这些规则与指针类型.vs的方法集相关联。值类型 有人可以解释一下原因吗(从界面表的角度) (威廉·肯尼迪博客的摘录) 规格摘要 方法集 类型可能具有与之关联的方法集。接口类型的方法集是其接口。任何其他类型T的方法集都包含以接收者类型T声明的所有方法。相应指针类型 T的方法集是所有以接收者 T或T声明的方法的集合(也就是说,它还包含方法T集)。进一步的规则适用于包含匿名字

  • 问题内容: 我最近正在研究虹膜框架。在实现处理程序时遇到一个问题。如下所示: 为了使用此控制器,我实现了以下输入脚本: 但是,当我编译代码时,收到以下错误消息: 在我将声明更改为: 然后,编译器通过,没有任何抱怨。 问题是:我认为以下语句是相等的,因为GO编译器将在表下进行转换: 为什么我不能用作为参数,而不是作为参数传递给? 感谢您的宝贵时间和分享。 问题答案: 参阅文件: 类型可能具有与之关联

  • 问题内容: 对于我来说,目前尚不清楚,在这种情况下,我想使用值接收器而不是始终使用指针接收器。 回顾一下文档: 该 文档 还说:“对于基本类型,切片和小型结构之类的类型,值接收器非常便宜,因此,除非该方法的语义要求使用指针,否则值接收器是高效且清晰的。” 首先, 它说“非常便宜”,但问题是它比指针接收器便宜。因此,我做了一个小的基准测试(基于要点的代码),向我展示了,即使对于只有一个字符串字段的结

  • 问题内容: 使用math.pow或**运算符哪个更有效?我什么时候应该使用另一个? 到目前为止,我知道可以返回一个或一个,如果您使用小数,该函数将返回一个浮点数 问题答案: 使用Power运算符将更快,因为它不会产生函数调用的开销。如果您反汇编Python代码,则可以看到以下内容: 请注意,我在这里使用变量作为指数,因为类似常数的表达式实际上是在编译时求值的。 现在,实际上,这种差异并不重要,正如