Maison > développement back-end > Golang > Pourquoi l'utilisation de `t` vs `*t` comme récepteur dans `fmt.Stringer` de Go conduit-elle à une boucle morte ?

Pourquoi l'utilisation de `t` vs `*t` comme récepteur dans `fmt.Stringer` de Go conduit-elle à une boucle morte ?

Patricia Arquette
Libérer: 2024-11-22 22:49:12
original
776 Les gens l'ont consulté

Why does using `t` vs `*t` as a receiver in Go's `fmt.Stringer` lead to a dead loop?

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())
}
Copier après la connexion

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)
}
Copier après la connexion

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))
}
Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal