Leçons du module (2/5)
Méthodes : récepteur de valeur vs pointeur
Une méthode en Go est une fonction avec un récepteur : un paramètre
spécial déclaré entre func et le nom de la méthode, qui lie la méthode
à un mec. Il n'y a pas de classes : les méthodes peuvent être définies sur
tout type nommé déclaré dans le package actuel.
Syntaxe
type Person struct {
Name string
}
func (p Person) Greet() string {
return "ciao " + p.Name
}
p := Person{Name: "Ada"}
fmt.Println(p.Greet()) // "ciao Ada"Le récepteur p Person fait de Greet une méthode de Person. À l'intérieur du
méthode, p est une variable comme les autres.
Récepteur de valeur vs récepteur de pointeur
// VALUE receiver: opera su una COPIA del valore
func (p Person) NameUpper() string {
return strings.ToUpper(p.Name)
}
// POINTER receiver: opera sul valore originale, può mutarlo
func (p *Person) Rename(n string) {
p.Name = n
}Avec le récepteur pointeur, vous pouvez éditer le récepteur et les modifications ils sont vus en dehors de la méthode. Avec le récepteur de valeur non — vous changeriez seulement la copie locale.
p := Person{Name: "Ada"}
p.Rename("Grace")
fmt.Println(p.Name) // "Grace" — modifica visibileQuand utiliser le récepteur pointeur
Règles empiriques, par ordre de priorité :
- Vous devez changer de récepteur → récepteur pointeur. Obligatoire.
- La structure est grande (des dizaines de champs, tableau à l'intérieur) → pointeur récepteur pour éviter des copies coûteuses.
- Cohérence : si AU MOINS une méthode du type a un récepteur de pointeur, utilisez récepteur pointeur pour les autres aussi. Convention très importante pour interfaces (Module 6).
- Petits types de « valeur » immuables (time.Time, nombres complexes, petits struct) → récepteur de valeur, lisible.
Méthodes sur les types non-struct
Vous pouvez définir des méthodes sur n'importe quel type NAMED déclaré dans votre package :
type Celsius float64
func (c Celsius) ToFahrenheit() float64 {
return float64(c)*9/5 + 32
}
t := Celsius(20)
fmt.Println(t.ToFahrenheit()) // 68Vous ne pouvez pas les définir sur des types d'autres packages (ex. int, string) : vous devez
créez d’abord un type nommé local.
Essayez-le vous-même
Ajoutez une méthode de chaîne Greet() (récepteur de valeur) à Person qui renvoie « bonjour <Nom> ».
Afficher l'indice
Récepteur entre parenthèses AVANT le nom de la méthode.
Solution disponible après 3 tentatives
Ajoutez une méthode Rename(n string) avec le récepteur POINTER qui modifie p.Name.
Afficher l'indice
Récepteur pointeur : `(p *Person)`.
Solution disponible après 3 tentatives
Quand utiliser un récepteur pointeur (p *T) ?
func (t ?T) M() { ... }Récapitulatif
- Méthode = fonction avec un récepteur :
func (r T) Nome(...) ... { ... }. - Récepteur de valeur : fonctionne sur copie ; Récepteur pointeur : fonctionne sur l'original.
- Go effectue la conversion
T↔*Tautomatiquement dans l'appel. - Pointeur récepteur quand : modification + grande struct + cohérence avec les autres méthodes du type.
- Ne mélangez jamais les récepteurs de valeur et de pointeur sur le même type.
- Les méthodes vont sur les types NAMED dans le package actuel (même non-struct).