Comprendre la différence entre t et *t : une étude de cas du package fmt
Dans Go, le package fmt offre de puissantes capacités de formatage , permettant aux développeurs de personnaliser la façon dont les valeurs sont imprimées. Cependant, une différence subtile entre t et *t peut conduire à un comportement inattendu, à savoir une boucle morte lorsqu'elle est utilisée dans une méthode réceptrice.
Considérez 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) } func main() { tt := &TT{3, 4, "5"} fmt.Printf(tt.String()) }
Ce code s'exécutera avec succès, en imprimant le contenu de la variable 'tt' sous la forme "tt={a:3, b:4, c:5}". Cependant, si nous modifions la méthode String comme suit :
func (t *TT) String() string { return fmt.Sprintf("%+v", t) }
Cela entraînera une boucle morte. La raison réside dans la façon dont le package fmt gère les valeurs qui implémentent la méthode String() (implémente l'interface fmt.Stringer).
Lorsque la valeur de 'tt' est transmise à fmt.Println, le package fmt vérifie si le type TT implémente la méthode String(). Puisque nous avons défini la méthode String() avec un récepteur de pointeur (*TT), la méthode définie pour TT n'inclut pas String(). Par conséquent, le package fmt n'appelle pas tt.String().
Par contre, dans l'extrait de code modifié, nous définissons la méthode String() avec un type de récepteur de *TT. Dans ce cas, la méthode définie pour TT inclut String(). Cependant, puisque nous transmettons tt qui est de type *TT, l'appel de tt.String() appelle essentiellement la méthode String() de manière récursive, ce qui entraîne une boucle infinie.
Pour éviter ce problème, il est conseillé de utilisez un type de récepteur différent pour la méthode String(). Une approche consiste à créer un nouveau type à l’aide du mot-clé type et à effectuer une conversion de type sur la valeur transmise. Cela crée un nouveau type sans méthode, évitant ainsi la boucle infinie.
Par exemple :
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t)) }
Dans ce cas, la conversion de t en TT2 garantit efficacement que la méthode String() ne sera pas être appelé de manière récursive, car TT2 n'a pas de méthode String().
Comprendre la distinction entre t et *t dans le contexte du package fmt est crucial pour évitez les comportements inattendus et assurez une exécution efficace du code.
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!