Récepteur et Interface
Les méthodes avec des récepteurs de valeur peuvent être appelées à la fois avec des valeurs et des pointeurs.
Les méthodes avec des récepteurs de pointeur ne peuvent être appelées qu'avec des pointeurs ou des valeurs adressables.
Par exemple,
type S struct {
data string
}
func (s S) Read() string {
return s.data
}
func (s *S) Write(str string) {
s.data = str
}
sVals := map[int]S{1: {"A"}}
// Vous pouvez uniquement appeler Read en utilisant une valeur
sVals[1].Read()
// Ceci ne compilera pas :
// sVals[1].Write("test")
sPtrs := map[int]*S{1: {"A"}}
// Les méthodes Read et Write peuvent toutes deux être appelées en utilisant un pointeur
sPtrs[1].Read()
sPtrs[1].Write("test")
De même, même si une méthode a un récepteur de valeur, elle peut satisfaire une interface utilisant un récepteur de pointeur.
type F interface {
f()
}
type S1 struct{}
func (s S1) f() {}
type S2 struct{}
func (s *S2) f() {}
s1Val := S1{}
s1Ptr := &S1{}
s2Val := S2{}
s2Ptr := &S2{}
var i F
i = s1Val
i = s1Ptr
i = s2Ptr
// Le code suivant ne compilera pas car s2Val est une valeur et la méthode f de S2 n'a pas de récepteur de valeur
// i = s2Val
Effective Go contient d'excellentes explications sur les pointeurs vs. valeurs.
Notes supplémentaires :
- Un type peut avoir un ensemble de méthodes avec des récepteurs de valeur et un ensemble de méthodes avec des récepteurs de pointeur
- L'ensemble de méthodes avec des récepteurs de valeur est un sous-ensemble de l'ensemble de méthodes avec des récepteurs de pointeur, mais pas l'inverse
- Règles
- Les objets de valeur peuvent uniquement utiliser l'ensemble de méthodes avec des récepteurs de valeur
- Les objets de pointeur peuvent utiliser l'ensemble de méthodes avec des récepteurs de valeur + l'ensemble de méthodes avec des récepteurs de pointeur
- Correspondance d'interface (ou implémentation)
- Le type correspond à l'interface s'il implémente toutes les méthodes de l'interface
- Plus précisément, il s'agit soit de l'ensemble de méthodes de valeur du type correspondant à l'interface, soit de l'ensemble de méthodes de pointeur correspondant à l'interface
Il existe deux types spécifiques de correspondance :
- Correspondance de l'ensemble de méthodes de valeur à l'interface
- Il est possible d'assigner un objet de valeur ou de pointeur à une variable d'interface car les deux contiennent l'ensemble de méthodes de valeur
- Correspondance de l'ensemble de méthodes de pointeur à l'interface
- Seul un objet de pointeur peut être assigné à une variable d'interface car seul l'ensemble de méthodes de pointeur correspond à l'interface
- Si un objet de valeur est assigné à une variable d'interface, il déclenchera un mécanisme de vérification de la vitalité de l'interface lors de la compilation
Quant à la raison pour laquelle i = s2Val déclenche une erreur, c'est parce que l'ensemble de méthodes de valeur et l'interface ne correspondent pas.