Jeśli typ użytkownika implementuje metodę
String() string
to przy użyciu tej wartości w funkcjach fmt (na przykład fmt.Println, fmt.Printf("%v"), pakiet log) ta metoda jest wywoływana w celu uzyskania reprezentacji tekstowej.
Warto zaimplementować String() dla typów użytkownika, aby uzyskać sensowne, czytelne dla człowieka wyjście zamiast standardowego z fmt (%v). Zaleca się, aby wyjście było zwięzłe, adekwatne do kontekstu użycia i, jeśli to możliwe, bezpieczne (bez ujawniania wrażliwych danych).
Przykład implementacji:
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) } // Output: Order[A123]: 99
Jeśli metoda została zaimplementowana z błędami lub nieadekwatnie, prowadzi to do logów z bezsensownym lub niebezpiecznym wyjściem, co utrudnia wyszukiwanie błędów.
Co jeśli twój typ implementuje metodę String(), ale używasz go jako wskaźnika, a nie wartości? Czy zostanie wywołana String()?
Odpowiedź: Metoda String() zostanie wywołana, jeśli jest zaimplementowana dla typu wskaźnika. Jeśli jest zaimplementowana tylko na wartości, ale w kodzie typ jest wskaźnikiem, metoda zostanie wywołana dzięki automatycznemu dereferencjowaniu w Go dla metod bez receivera wskaźnika. Zwykle nie jest to problem, ale jeśli metoda została zaimplementowana tylko dla receivera wskaźnika, a wywołujesz ją dla wartości, to pojawi się błąd kompilacji.
Przykład:
type X struct{} func (x *X) String() string { return "ptr" } fmt.Println(X{}) // błąd: X nie implementuje String fmt.Println(&X{}) // ok, metoda zostanie wywołana
Historia
W dużym projekcie typ błędu zaimplementował String() tylko dla receivera wskaźnika (
func (err *MyErr) String() string). Z tego powodu, przy zwracaniu wartości błędu (nie wskaźnika) w logach pojawiało się bezsensowne{}zamiast użytecznej wiadomości. Błąd długo nie był zauważany.
Historia
Jeden z typów przechowywał wrażliwe dane, a przy błędnej implementacji String() (wyświetlano pola jawnie) hasła użytkowników zaczęły pojawiać się w logach produkcyjnych. Potrzebna była audyt bezpieczeństwa.
Historia
Użycie automatycznego generowania String() spowodowało, że podczas aktualizacji struktury nowy format wyjścia nie zgadzał się z poprzednim, logi stały się nieczytelne, a analiza logów przez zewnętrzne systemy uległa zakłóceniu.