Il est très peu clair pour moi dans quel cas je voudrais utiliser un récepteur de valeur au lieu de toujours utiliser un récepteur de pointeur.
Pour récapituler à partir des documents:
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
La documentation dit également "Pour les types tels que les types de base, les tranches et les petites structures, un récepteur de valeur est très bon marché donc à moins que la sémantique de la méthode ne nécessite un pointeur, un récepteur de valeur est efficace et clair."
Premier point, il dit qu'il est "très bon marché", mais la question est plus est-il moins cher que le récepteur de pointeur. J'ai donc fait un petit benchmark (code sur l'essentiel) qui m'a montré que le récepteur de pointeur est plus rapide même pour une structure qui n'a qu'un seul champ de chaîne. Voici les résultats:
// Struct one empty string property
BenchmarkChangePointerReceiver 2000000000 0.36 ns/op
BenchmarkChangeItValueReceiver 500000000 3.62 ns/op
// Struct one zero int property
BenchmarkChangePointerReceiver 2000000000 0.36 ns/op
BenchmarkChangeItValueReceiver 2000000000 0.36 ns/op
(Modifier: veuillez noter que le deuxième point est devenu invalide dans les nouvelles versions de go, voir les commentaires) .
Deuxième point dit-il, c'est "efficace et clair", ce qui est plus une question de goût, n'est-ce pas? Personnellement, je préfère la cohérence en utilisant partout de la même manière. Efficacité dans quel sens? en termes de performances, il semble que les pointeurs soient presque toujours plus efficaces. Peu de tests avec une propriété int ont montré un avantage minimal du récepteur Value (plage de 0,01-0,1 ns / op)
Quelqu'un peut-il me dire un cas où un récepteur de valeur a clairement plus de sens qu'un récepteur de pointeur? Ou est-ce que je fais quelque chose de mal dans le benchmark, ai-je négligé d'autres facteurs?