Den Unterschied zwischen t und *t verstehen: Eine Fallstudie aus dem fmt-Paket
In Go bietet das fmt-Paket leistungsstarke Formatierungsfunktionen , sodass Entwickler die Art und Weise, wie Werte gedruckt werden, anpassen können. Allerdings kann ein subtiler Unterschied zwischen t und *t zu unerwartetem Verhalten führen, nämlich zu einer toten Schleife, wenn es innerhalb einer Empfängermethode verwendet wird.
Beachten Sie den folgenden Codeausschnitt:
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()) }
Dieser Code wird erfolgreich ausgeführt und gibt den Inhalt der Variablen „tt“ als „tt={a:3, b:4, c:5}“ aus. Wenn wir jedoch die String-Methode wie folgt ändern:
func (t *TT) String() string { return fmt.Sprintf("%+v", t) }
Dies führt zu einer toten Schleife. Der Grund liegt in der Art und Weise, wie das fmt-Paket Werte verarbeitet, die die String()-Methode implementieren (implementiert die fmt.Stringer-Schnittstelle).
Wenn der Wert von 'tt' an fmt.Println übergeben wird, wird das fmt-Paket prüft, ob der Typ TT die String()-Methode implementiert. Da wir die String()-Methode mit einem Zeigerempfänger (*TT) definiert haben, enthält die für TT festgelegte Methode String() nicht. Folglich ruft das fmt-Paket tt.String() nicht auf.
Andererseits definieren wir im modifizierten Code-Snippet die String()-Methode mit einem Empfängertyp *TT. In diesem Fall umfasst die für TT festgelegte Methode String(). Da wir jedoch tt übergeben, das vom Typ *TT ist, ruft der Aufruf von tt.String() im Wesentlichen die String()-Methode rekursiv auf, was zu einer Endlosschleife führt.
Um dieses Problem zu verhindern, ist es ratsam, dies zu tun Verwenden Sie einen anderen Empfängertyp für die String()-Methode. Ein Ansatz besteht darin, mit dem Schlüsselwort „type“ einen neuen Typ zu erstellen und eine Typkonvertierung für den übergebenen Wert durchzuführen. Dadurch wird ein neuer Typ ohne Methoden erstellt und die Endlosschleife vermieden.
Zum Beispiel:
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t)) }
In diesem Fall stellt die Konvertierung von t in TT2 effektiv sicher, dass die String()-Methode dies nicht tut rekursiv aufgerufen werden, da TT2 keine String()-Methode hat.
Das Verständnis der Unterscheidung zwischen t und *t im Kontext des fmt-Pakets ist von entscheidender Bedeutung um unerwartetes Verhalten zu vermeiden und eine effiziente Codeausführung sicherzustellen.
Das obige ist der detaillierte Inhalt vonWarum führt die Verwendung von „t' vs. „*t' als Empfänger in „fmt.Stringer' von Go zu einer toten Schleife?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!