Si un tipo personalizado implementa el método
String() string
entonces, al utilizar este valor en funciones fmt (por ejemplo, fmt.Println, fmt.Printf("%v"), el paquete log), se llama a este método para obtener la representación en cadena.
Es recomendable implementar String() para tipos personalizados que representan entidades, para obtener una salida legible y significativa en lugar de la estándar de fmt (%v). Se sugiere que la salida sea breve, adecuada al contexto de uso y, si es posible, segura (sin filtrar datos sensibles).
Ejemplo de implementación:
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) } // Salida: Order[A123]: 99
Si el método se implementa de manera incorrecta o inadecuada, esto lleva a registros con salidas sin sentido o peligrosas, dificultando la búsqueda de errores.
¿Qué sucede si tu tipo implementa el método String(), pero lo usas como puntero, no como valor? ¿Se llamará String()?
Respuesta: Se llamará al método String() si está implementado para el tipo-puntero. Si está implementado solo para el valor, pero en el código el tipo es un puntero, el método se invocará gracias a la desreferenciación automática de Go para métodos sin receptor de puntero. Normalmente no es un problema, pero si el método está implementado solo para el receptor de puntero y lo llamas para un valor, entonces habrá un error de compilación.
Ejemplo:
type X struct{} func (x *X) String() string { return "ptr" } fmt.Println(X{}) // error: X no implementa String fmt.Println(&X{}) // ok, se llamará al método
Historia
En un proyecto grande, el tipo de error implementó String() solo en el receptor de puntero (
func (err *MyErr) String() string). Debido a esto, al devolver el valor del error (no un puntero) se mostraba en los registros{}en lugar de un mensaje útil. El error no fue detectado durante mucho tiempo.
Historia
Uno de los tipos almacenaba datos sensibles, y debido a una implementación incorrecta de String() (se mostraban los campos explícitamente), las contraseñas de los usuarios comenzaron a aparecer en los registros de producción. Se necesitó una auditoría de seguridad.
Historia
El uso de la generación automática de String() llevó a que al actualizar la estructura, el nuevo formato de salida no coincidiera con el anterior, los registros se volvieron ilegibles y se interrumpió el análisis de registros por sistemas externos.