Comprendre les nuances de *t vs. t dans l'invocation de la méthode Go
Dans Go, l'utilisation de pointeurs ('*') dans Les récepteurs de méthode peuvent avoir des ramifications importantes sur le fonctionnement de la méthode. Cette différence est mise en évidence dans l'extrait de code suivant :
package main import "fmt" type TT struct { a int b float32 c string } func (t *TT) String() string { return fmt.Sprintf("%+v", *t) // Original implementation } // func (t *TT) String() string { // return fmt.Sprintf("%+v", t) // Altered implementation // } func main() { tt := &TT{3, 4, "5"} fmt.Printf(tt.String()) }
L'implémentation originale de la méthode String() utilise un récepteur de pointeur (*TT), ce qui évite l'écueil d'accéder à un pointeur nul si t est nul . Cependant, la modification de la méthode String() pour utiliser un récepteur sans pointeur (TT) entraîne une boucle morte.
Raison de la boucle morte :
La clé de la compréhension de ce comportement réside dans la façon dont le package fmt de Go gère les types qui implémentent l'interface fmt.Stringer (c'est-à-dire les types qui fournissent une méthode String() personnalisée). Lors de l'impression d'une valeur de type *TT, fmt.String() vérifiera d'abord si *TT implémente une méthode String() valide. Si tel est le cas, il invoquera cette méthode pour obtenir la représentation sous forme de chaîne de la valeur. Cela fonctionne bien lorsque *TT a un récepteur de pointeur car l'ensemble de méthodes de *TT inclut la méthode String().
Cependant, lorsque le récepteur de String() est remplacé par un type non-pointeur (c'est-à-dire, TT), le problème se pose. Dans ce cas, l'ensemble de méthodes de TT inclut la méthode String(), ce qui signifie que lorsque fmt.String() tente d'imprimer la valeur de t (une instance de TT), il appellera t.String(), qui dans turn s'appellera à nouveau, conduisant à une récursion infinie.
Prévenir la boucle morte :
Pour éviter la boucle morte, on peut utiliser une technique appelée conversion de type. En créant un nouveau type à l'aide du mot-clé type et en convertissant la valeur passée à fmt.String(), on peut éviter la récursion infinie :
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t)) }
Dans ce cas, le nouveau type (TT2) n'a aucune méthode , donc lorsque fmt.String() tente d'imprimer la valeur convertie, il n'invoque pas de méthode String() sur le type converti.
Conclusion :
Compréhension la différence entre *t et t dans les récepteurs de méthodes est cruciale pour éviter les pièges potentiels lors de l'impression de types personnalisés à l'aide de la fonction fmt.String(). En examinant attentivement le type de récepteur et en utilisant la conversion de type si nécessaire, on peut éviter les boucles mortes et garantir le bon fonctionnement des invocations de méthode.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!