您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

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

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()EmbeddedMyType方法,仅包含的方法*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,在该方法方法集中包括了提升的方法,如下所示:

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

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

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

有一种非常相似的情况,即当您有一个包装了值的接口值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))
其他 2022/1/1 18:15:11 有466人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶