Если пользовательский тип реализует метод
String() string
то при использовании этого значения в функциях fmt (например, fmt.Println, fmt.Printf("%v"), log-пакете) вызывается этот метод для получения строкового представления.
Реализовать String() стоит для пользовательских типов-сущностей, чтобы получать осмысленный человекочитаемый вывод вместо стандартного от fmt (%v). Рекомендуется делать вывод кратким, адекватным контексту использования, и, по возможности, безопасным (без утечки чувствительных данных).
Пример реализации:
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
Если метод реализован с ошибками или неадекватно, это приводит к логам с бессмысленным или опасным выводом, затрудняет поиск багов.
Что если ваш тип реализует метод String(), но вы используете его как указатель, а не значение? Будет ли вызван String()?
Ответ: Метод String() будет вызван, если у типа-указателя он реализован. Если реализован только на значении, но в коде тип — указатель, метод вызовется благодаря авторазыменованию Go для методов без pointer receiver. Обычно это не проблема, но если метод реализован только на pointer receiver, а вы вызываете его для значения, то будет ошибка компиляции.
Пример:
type X struct{} func (x *X) String() string { return "ptr" } fmt.Println(X{}) // error: X does not implement String fmt.Println(&X{}) // ok, вызовется метод
История
В крупном проекте тип ошибки реализовал String() только на pointer receiver (
func (err *MyErr) String() string). Из-за этого при возвращении значения ошибки (не указателя) в логах выводилось бесполезное{}вместо полезного сообщения. Баг долго не замечали.
История
Один из типов хранил сенситивные данные, и при ошибочной реализации String() (выводили поля в явном виде) пользовательские пароли начали появляться в production логах. Понадобился аудит безопасности.
История
Использование автоматической генерации String() привело к тому, что при обновлении структуры новый формат вывода не совпал с предыдущим, логи стали нечитабельны, нарушился парсинг логов сторонними системами.