Saltar al contenido principal
eLearner.app
Módulo 6 · Lección 4 de 529/50 en el curso~10 min
Lecciones del módulo (4/5)

La interfaz Stringer

fmt.Stringer es probablemente la interfaz estándar más utilizada en todos Biblioteca estándar de Go. Es la demostración perfecta del poder. de pequeñas interfaces.

Definición

Go
type Stringer interface {
    String() string
}

Una sola firma. Cualquier tipo que defina String() string satisface eso. Y fmt reconoce esta interfaz: cuando pasas un valor a fmt.Print*, si implementa Stringer, el resultado de String() se utiliza en lugar de la representación predeterminada.

Ejemplo

Go
type Point struct{ X, Y int }

func (p Point) String() string {
    return fmt.Sprintf("(%d,%d)", p.X, p.Y)
}

fmt.Println(Point{1, 2})              // (1,2)
fmt.Printf("%v %s\n", Point{3, 4}, Point{5, 6})
// (3,4) (5,6)

El mismo valor se imprime con formato personalizado en %v, %s, Println, Sprint, log, etc. Todo con solo definir un método.

Cuando tiene sentido

  • Tipos que modelan un dominio (ids, códigos, coordenadas, enumeraciones).
  • Errores con una representación legible por humanos (consulte la siguiente lección sobre error).
  • Tipos que registras con frecuencia y para los que deseas un formato fijo.

No para todo: si el tipo es simple y la representación por defecto Está bien, no agregues ruido.

Tipos de enumeración: patrón común con iota

Go
type Status int

const (
    OK Status = iota
    WARN
    ERR
)

func (s Status) String() string {
    switch s {
    case OK:   return "OK"
    case WARN: return "WARN"
    case ERR:  return "ERR"
    default:   return "UNKNOWN"
    }
}

fmt.Println(OK, WARN, ERR)   // OK WARN ERR

Sin String(), fmt.Println(OK) imprimiría 0. Con String(), imprime el nombre simbólico. El CÓDIGOPH4 La herramienta genera este patrón automáticamente.

Cuidado con la recursividad infinita

Go
type T int
func (t T) String() string {
    return fmt.Sprintf("%d", int(t))  // OK: cast to int breaks the recursion
}

Stringer en un receptor de puntero

Si String() tiene un receptor de puntero, sólo *T satisface Stringer. Con fmt.Println(t) (un valor), Go mira el conjunto de métodos de T, no lo encuentra y usa el formato predeterminado. Para evitar esto, **valor El receptor ** generalmente se usa para String() (es una "vista"; no modificar nada).

Pruébalo

Ejercicio#go.m6.l4.e1
Intentos: 0Cargando...

Implemente String() en Point para que devuelva (X,Y).

Cargando editor...
Mostrar pista

Utilice `fmt.Sprintf` para formatear los campos.

Solución disponible después de 3 intentos

Ejercicio#go.m6.l4.e2
Intentos: 0Cargando...

Implemente String() en un tipo Estado (int): 0 → 'OK', 1 → 'WARN', de lo contrario → 'ERR'.

Cargando editor...
Mostrar pista

Activar el valor del receptor; recuerde proporcionar un valor predeterminado.

Solución disponible después de 3 intentos

Cuestionario#go.m6.l4.e3
Listo

¿Qué firma debe tener el método para satisfacer fmt.Stringer?

Go
func (x T) ??? {}
Opciones de respuesta

Resumen

  • CÓDIGOPH0.
  • Su implementación cambia la forma en que fmt.Print* representa el tipo.
  • Idiomatic para enumeraciones (iota), tipos de dominio, códigos/identificadores.
  • Nunca llame a fmt.Sprintf("%s", t) en t dentro de String() (recursividad).
  • Convención: receptor de valores para String() (sin mutación, evita "sorpresas en el conjunto de métodos").