Wenn ein benutzerdefinierter Typ die Methode
String() string
implementiert, wird bei der Verwendung dieses Werts in Funktionen von fmt (z. B. fmt.Println, fmt.Printf("%v"), im log-Paket) diese Methode aufgerufen, um die textuelle Darstellung zu erhalten.
Es ist ratsam, String() für benutzerdefinierte Entitätstypen zu implementieren, um eine sinnvolle, menschenlesbare Ausgabe anstelle der Standardausgabe von fmt (%v) zu erhalten. Empfohlen wird eine kurze, kontextangemessene Ausgabe, die, wo möglich, sicher ist (ohne Leckage sensibler Daten).
Beispiel für die Implementierung:
type Order struct { ID string Amount int } func (o Order) String() string { return fmt.Sprintf("Order[%s]: %d", o.ID, o.Amount) } func main() { o := Order{"A123", 99} fmt.Println(o) } // Ausgabe: Order[A123]: 99
Wenn die Methode fehlerhaft oder unangemessen implementiert ist, kann dies zu Protokollen mit sinnlosem oder gefährlichem Inhalt führen und die Fehlersuche erschweren.
Was passiert, wenn Ihr Typ die Methode String() implementiert, Sie ihn aber als Zeiger und nicht als Wert verwenden? Wird String() aufgerufen?
Antwort: Die Methode String() wird aufgerufen, wenn sie für den Zeiger-Typ implementiert ist. Wenn sie nur für den Wert implementiert ist, aber im Code der Typ ein Zeiger ist, wird die Methode aufgrund des automatischen Dereferenzierens in Go für Methoden ohne Pointer Receiver aufgerufen. Normalerweise ist das kein Problem, aber wenn die Methode nur für den Pointer Receiver implementiert ist und Sie sie für den Wert aufrufen, kommt es zu einem Kompilierfehler.
Beispiel:
type X struct{} func (x *X) String() string { return "ptr" } fmt.Println(X{}) // Fehler: X implementiert nicht String fmt.Println(&X{}) // ok, die Methode wird aufgerufen
Geschichte
In einem großen Projekt implementierte der Fehlertyp String() nur für den Pointer Receiver (
func (err *MyErr) String() string). Deshalb wurde beim Zurückgeben eines Fehlerwerts (nicht Zeiger) im Protokoll{}anstelle einer nützlichen Nachricht ausgegeben. Der Fehler wurde lange Zeit nicht bemerkt.
Geschichte
Ein Typ speicherte sensible Daten, und durch eine fehlerhafte Implementierung von String() (die Felder wurden explizit ausgegeben) erschienen Benutzerpasswörter in Produktionsprotokollen. Eine Sicherheitsüberprüfung war erforderlich.
Geschichte
Die Verwendung der automatischen Generierung von String() führte dazu, dass beim Aktualisieren der Struktur das neue Ausgabeformat nicht mit dem vorherigen übereinstimmte, die Protokolle unlesbar wurden und das Parsing von Protokollen durch externe Systeme gestört wurde.