Home >Backend Development >Golang >X does not implement Y (...method has a pointer receiver)

X does not implement Y (...method has a pointer receiver)

WBOY
WBOYforward
2024-02-12 23:27:08929browse

X 没有实现 Y(...方法有一个指针接收器)

In this article, php editor Xiaoxin will discuss a problem about X's failure to implement Y. In this problem, we used a pointer receiver approach. Through this method, we can better understand why X cannot achieve Y and find ways to solve this problem. In the following content, we will discuss this problem in detail and provide some solutions.

Question content

There have been several Q&A's on the "X does not implement Y (...method has a pointer receiver)" question, but for me , they seem to be talking about different things and don't apply to my specific situation.

So instead of making the question very specific, I'm making it broad and abstract - it seems like there are a few different situations that could cause this error to occur, can someone summarize it?

How to avoid this problem, and if it occurs, what are the possibilities? Thanks.

Workaround

This compile-time error occurs when you try to assign or pass (or convert) a concrete type to an interface type; and the type itself does not Implementing this interface only implements a pointer to the type.

Short summary: Assignment to a variable An interface type is valid if the assigned value implements the interface to which it is assigned. If its method set is a superset of the interface, it will implement it. The method set of pointer types includes methods with pointer and non-pointer receivers. The method set for non-pointer types only includes methods with non-pointer receivers.

Let’s look at an example:

type stringer interface {
    string() string
}

type mytype struct {
    value string
}

func (m *mytype) string() string { return m.value }

stringer The interface type has only one method: string(). Any value stored in interface value stringer must have this method. We also created a mytype and created a method mytype.string() with a pointerreceiver. This means that the string() method is in the method set of type *mytype, but not in mytype.

When we try to assign a value of

mytype to a variable of type stringer, we receive the following error:

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)

But if we try to assign a value of type

*mytype to stringer , everything works fine:

s = &m
fmt.println(s)

We get the expected result (try it on

go playground):

something

So getting this compile time error requires:

    The assigned (or passed or converted)
  • non-pointervalue of a specific type
  • The interface type being assigned (or passed or converted)
  • Concrete types have the methods required by the interface, but have
  • pointer receivers

Possibility of solving the problem:

    A pointer to a value must be used and its method set will include methods with pointer receivers
  • Or the receiver type must be changed to
  • non-pointer, so the method set of the non-pointer concrete type will also contain the method (thereby satisfying the interface). This may or may not be possible, as if the method must modify the value, a non-pointer receiver is not an option.
Structure and embedding

When using

structures and embedding , it is usually not "you" implementing the interface (providing method implementations), but rather the type embedded in the struct. Just like this example:

type mytype2 struct {
    mytype
}

m := mytype{value: "something"}
m2 := mytype2{mytype: m}

var s stringer
s = m2 // compile-time error again

An error occurred when compiling again because the method set of

mytype2 does not contain the string() method embedded in mytype, only *mytype2 method set, so the following method is valid (go to the playground in ):

var s stringer
s = &m2

We can also make it work if we embed

*mytype and just use non-pointers mytype2 (go to the playground in ):

type mytype2 struct {
    *mytype
}

m := mytype{value: "something"}
m2 := mytype2{mytype: &m}

var s stringer
s = m2
Also, no matter what we embed (

mytype

or *mytype), if we use the pointer *mytype2, it will always work (in GOAGUN):

type mytype2 struct {
    *mytype
}

m := mytype{value: "something"}
m2 := mytype2{mytype: &m}

var s stringer
s = &m2
Relevant sections in the specification (from the

Structural Types

section):

给定一个结构体类型 s 和一个名为 t 的类型,提升的方法包含在该结构体的方法集中,如下所示:

  • 如果 s 包含匿名字段 t,则 s*s 的方法集均包含接收者为 t 的提升方法。 *s 的方法集还包括接收者 *t 的提升方法。
  • 如果 s 包含匿名字段 *t,则 s*s 的方法集都包含接收者为 t*t 的提升方法。

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

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

如果我们使用指向嵌入器的指针值,则无论嵌入类型是否是指针,指向嵌入器的指针的方法集始终都会获取具有指针和非指针接收器的方法(从嵌入类型)。

注意:

有一个非常相似的情况,即当您有一个包含 mytype 值的接口值时,并且您尝试 类型断言 另一个接口值,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))

The above is the detailed content of X does not implement Y (...method has a pointer receiver). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete