Cette erreur de compilation se produit lorsque vous essayez de céder ou de transmettre (ou convertir) un béton de type pour un type d'interface; et le type lui-même n'implémente pas l'interface, seulement un pointeur vers le type.
Voyons un exemple:
type Stringer interface {
String() string
}
type MyType struct {
value string
}
func (m *MyType) String() string { return m.value }
L' Stringer
type d'interface a une méthode uniquement: String()
. Toute valeur qui est stockée dans une interface valeur Stringer
doit avoir cette méthode. Nous avons également créé un MyType
, et nous avons créé une méthode MyType.String()
avec pointeur récepteur. Cela signifie que l' String()
méthode est la méthode de l' *MyType
type, mais pas dans celui de la MyType
.
Lorsque l'on tente d'attribuer une valeur de MyType
pour une variable de type Stringer
, nous obtenons l'erreur en question:
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 tout est ok si nous essayons d'affecter une valeur de type *MyType
de Stringer
:
s = &m
fmt.Println(s)
Et nous obtenons le résultat attendu (essayez sur la Aller de l'aire de Jeux):
something
Donc, les exigences pour obtenir cette erreur de compilation:
- Une valeur de non-pointeur de type concret d'être affecté (ou passé, ou converti)
- Un type d'interface étant assigné (ou passé, ou convertis)
- Le type de béton nécessaire de la méthode de l'interface, mais avec un pointeur récepteur
Possibilités pour résoudre le problème:
- Un pointeur vers la valeur doit être utilisé, dont la méthode d'ensemble comprendra la méthode avec le pointeur de récepteur
- Ou le type du récepteur doit être changé pour non-pointeur, de sorte que la méthode de la non-pointeur de type de béton contiendra également la méthode (et de répondre ainsi à l'interface). Cela peut ou peut ne pas être viable, comme si la méthode a pour modifier la valeur, un non-pointeur récepteur n'est pas une option.
Les structures et l'incorporation de
Lors de l'utilisation des structures et de l'intégration, il n'est souvent pas "vous" qui implémentent une interface (fournir une méthode de mise en œuvre), mais un type de vous intégrer dans votre struct
. Comme dans cet exemple:
type MyType2 struct {
MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: m}
var s Stringer
s = m2 // Compile-time error again
Encore une fois, erreur de compilation, car la méthode de MyType2
ne contient pas l' String()
méthode de l'embedded MyType
, seule la méthode de *MyType2
, de sorte que les œuvres suivantes (essayez sur la Aller de l'aire de Jeux):
var s Stringer
s = &m2
Nous pouvons également le faire fonctionner, si nous intégrer *MyType
et en utilisant seulement un non-pointeur MyType2
(essayez sur la Aller de l'aire de Jeux):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = m2
Aussi, tout ce que nous intégrer ( MyType
ou *MyType
), si on utilise un pointeur *MyType2
, il le sera toujours (essayer sur les Aller de l'aire de Jeux):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = &m2
Section pertinente de la spec (à partir de la section Struct types):
Étant donné un type struct S
et un type nommé T
, promu méthodes sont inclus dans la méthode d'ensemble de la structure comme suit:
- Si
S
contient un anonyme, un champ T
, la méthode des ensembles de S
et *S
à la fois inclure le promu méthodes avec récepteur T
. La méthode de *S
comprend également promu méthodes avec récepteur *T
.
- Si
S
contient un anonyme, un champ *T
, la méthode des ensembles de S
et *S
à la fois inclure le promu méthodes avec récepteur T
ou *T
.
Donc, en d'autres mots: si nous rajoutons un non-type de pointeur, la méthode de la non-pointeur embedder ne reçoit que les méthodes non-pointeur de récepteurs (à partir de l'embedded type).
Si nous rajoutons un type pointeur, la méthode de la non-pointeur embedder obtient des méthodes à la fois avec le pointeur et non-pointeur de récepteurs (à partir de l'embedded type).
Si l'on utilise une valeur de pointeur à l'embedder, indépendamment du fait que l'intégré est de type pointeur ou pas, la méthode du pointeur à l'embedder obtient toujours des méthodes à la fois avec le pointeur et non-pointeur de récepteurs (à partir de l'embedded type).
Note:
Il est très similaire, à savoir lorsque vous disposez d'une interface de valeur qui encapsule une valeur de MyType
, et vous essayez de type affirmer une autre interface de valeur, Stringer
. Dans ce cas, l'affirmation sera pas pour les raisons décrites ci-dessus, mais nous sommes un peu différents à l'exécution d'erreur:
m := MyType{value: "something"}
var i interface{} = m
fmt.Println(i.(Stringer))
Exécution de panique (essayez sur la Aller de l'aire de Jeux):
panic: interface conversion: main.MyType is not main.Stringer:
missing method String
De tenter de les convertir à la place du type affirmer, nous obtenons l'erreur de compilation que nous parlons:
m := MyType{value: "something"}
fmt.Println(Stringer(m))