Maison  >  Article  >  développement back-end  >  X n'implémente pas Y (...la méthode a un récepteur de pointeur)

X n'implémente pas Y (...la méthode a un récepteur de pointeur)

WBOY
WBOYavant
2024-02-12 23:27:08867parcourir

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

L'éditeur php Xiaoxin discutera d'un problème concernant l'échec de X à implémenter Y dans cet article. Dans ce problème, nous avons utilisé une approche de récepteur pointeur. Grâce à cette méthode, nous pouvons mieux comprendre pourquoi X ne peut pas atteindre Y et trouver des moyens de résoudre ce problème. Dans le contenu suivant, nous discuterons de ce problème en détail et proposerons quelques solutions.

Contenu de la question

Il y a déjà quelques questions et réponses sur la question "X n'implémente pas Y (...la méthode a un récepteur de pointeur)", mais pour moi, elles semblent parler de choses différentes et ne s'appliquent pas à ma situation spécifique.

Donc, au lieu de rendre la question très spécifique, je vais la rendre large et abstraite - il semble qu'il existe plusieurs situations différentes qui pourraient provoquer cette erreur, quelqu'un peut-il la résumer ?

Comment éviter ce problème et si cela se produit, quelles sont les possibilités ? Merci.

Solution

Cette erreur de compilation se produit lorsque vous essayez d'attribuer ou de transmettre (ou de convertir) un type concreteà un type d'interface et que le type lui-même n'implémente pas l'interface, seulement un pointeur vers le type Pointer ; .

Court résumé : Une affectation à une variableLe type d'interface est valide si la valeur attribuée implémente l'interface à laquelle elle est affectée. Si son ensemble de méthodes est un sur-ensemble de l'interface, il l'implémentera. L’ensemble de méthodes de types de pointeurs comprend des méthodes avec des récepteurs pointeurs et non-pointeurs. La méthode définie pour les types sans pointeur uniquement inclut les méthodes avec des récepteurs sans pointeur.

Voyons un exemple :

type stringer interface {
    string() string
}

type mytype struct {
    value string
}

func (m *mytype) string() string { return m.value }
Le type d'interface stringer n'a qu'une seule méthode : string(). Toute valeur stockée dans la valeur d'interface stringer doit avoir cette méthode. Nous avons également créé un mytype et créé une méthode mytype.string() avec un

pointerstringer 接口类型只有一个方法:string()。存储在接口值 stringer 中的任何值都必须具有此方法。我们还创建了一个 mytype,并创建了一个带有指针接收器的方法 mytype.string()。这意味着 string() 方法位于 *mytype 类型的 方法集 中,但是不在 mytypereceiver. Cela signifie que la méthode string() est dans le

ensemble de méthodes

du type *mytype, mais pas dans mytype. mytype 的值分配给 stringer

Lorsque nous essayons de convertir une variable de type

nous obtenons l'erreur suivante : *mytype 类型的值分配给 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)

Mais si on essaie d'ajouter

, tout fonctionne bien :

s = &m
fmt.println(s)
Nous avons obtenu le résultat attendu (essayez-le sur

go terrain de jeu

) :

something

D'où l'obligation d'obtenir cette erreur de compilation :
  • Une
  • valeur sans pointeur
  • d'un type concret
  • qui est allouée (ou transmise ou convertie)
  • Le type d'interface attribué (ou transmis ou converti) Un type concret possède les méthodes requises par l'interface, mais possède un
  • récepteur de pointeur

Possibilité de résoudre le problème :
  • Un pointeur vers une valeur doit être utilisé et son ensemble de méthodes inclura des méthodes avec des récepteurs de pointeur ou le type de récepteur doit être modifié en
  • non-pointer
, donc l'ensemble de méthodes du type concret sans pointeur contiendra également la méthode (satisfaisant ainsi l'interface). Cela peut être possible ou non, car si la méthode doit modifier la valeur, un récepteur sans pointeur n'est pas une option.

Structure et intégration Lors de l'utilisation de structstructs et de l'intégration

, ce n'est généralement pas « vous » qui implémentez l'interface (en fournissant des implémentations de méthodes), mais plutôt le type intégré dans

. Comme cet exemple : mytype2的方法集不包含内嵌mytypestring()方法,只有*mytype2

type mytype2 struct {
    mytype
}

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

var s stringer
s = m2 // compile-time error again
Une erreur s'est produite lors de la nouvelle compilation, à cause de la méthode définie par , donc la méthode suivante fonctionne (dans

Aller au terrain de jeu

) : *mytype 并仅使用非指针 mytype2

var s stringer
s = &m2
Nous pouvons également le faire fonctionner si nous intégrons *mytype et utilisons simplement des non-pointeurs

mytype2 (dans

Go to Playgroundmytype*mytype),如果我们使用指针 *mytype2) :

type mytype2 struct {
    *mytype
}

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

var s stringer
s = m2
De plus, peu importe ce que nous intégrons (

), cela fonctionne toujours (dans

Go to the Playground) :

type mytype2 struct {
    *mytype
}

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

var s stringer
s = &m2

Section pertinente de la spécification (de la section 🎜Types de structure🎜) : 🎜

给定一个结构体类型 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))

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer