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.