DMarlon Studio

Lección 4 · 4 de 20

Stringer y formato de sus tipos · Go

Decida cómo se escriben sus tipos en Go con el método String (fmt.Stringer) y vea qué hacen %v, %+v, %#v, %d y los anchos con ellos.

Go · Stringer y formato de sus tipos en DMarlon Studio: el código del ejemplo y su salida en la terminal

fmt busca en cada valor un método String() string; si lo tiene, el valor cumple la interfaz `fmt.Stringer` y se escribe con él. Status es un entero con constantes creadas con `iota` (0, 1, 2), y su String las traduce con un array: Shipped sale como shipped, no como 1.

Money guarda céntimos en un int64 para no arrastrar errores de redondeo, y su String los escribe como 259.99 EUR. Por eso fmt.Println(o.Status, o.Total) da textos legibles sin ninguna conversión a mano.

Con un struct, %v escribe los campos entre llaves y usa el String de cada uno: {1042 259.99 EUR shipped}. `%+v` añade los nombres de los campos, muy útil para depurar. `%#v` escribe sintaxis de Go (main.Order{ID:1042, Total:25999, Status:1}) y no llama a String.

Solo los verbos de texto (%v, %s, %q, %x) llaman a String. Con `%d` sale el número que hay debajo: 1 25999. Los anchos funcionan sobre el texto que devuelve String: %-12s alinea a la izquierda y %12v, a la derecha.

Una trampa: dentro de String no escriba el propio valor con %v o %s, porque fmt volvería a llamar a String sin fin. Money usa %d, que no lo llama, así que no hay problema.

Código · main.go

package mainimport "fmt"type Status intconst (	Pending Status = iota	Shipped	Delivered)// String makes Status a fmt.Stringer: %v and %s call it.func (s Status) String() string { return [...]string{"pending", "shipped", "delivered"}[s] }type Money int64 // amount in centsfunc (m Money) String() string { return fmt.Sprintf("%d.%02d EUR", m/100, m%100) }type Order struct {	ID     int	Total  Money	Status Status}func main() {	o := Order{ID: 1042, Total: 25999, Status: Shipped}	fmt.Println("status:", o.Status, "| total:", o.Total)	fmt.Printf("%v\n", o)	fmt.Printf("%+v\n", o)	fmt.Printf("%#v\n", o)                           // Go syntax: String is not used	fmt.Printf("%d %d\n", o.Status, o.Total)         // %d prints the plain number	fmt.Printf("|%-12s|%12v|\n", Delivered, o.Total) // width and alignment}

Salida · go run main.go

status: shipped | total: 259.99 EUR
{1042 259.99 EUR shipped}
{ID:1042 Total:259.99 EUR Status:shipped}
main.Order{ID:1042, Total:25999, Status:1}
1 25999
|delivered   |  259.99 EUR|

Para recordar

  • Un tipo con String() string es un fmt.Stringer.
  • %v y %s usan String; %d escribe el número.
  • %+v añade los nombres de los campos; %#v, la sintaxis de Go.
  • Los anchos (%-12s) se aplican al texto de String.
  • Dentro de String, no formatee el propio valor con %v.

Ejercicio

Añada un estado Cancelled a las constantes y a la tabla de String, y cambie el pedido a ese estado. Después escriba fmt.Printf("%q\n", o.Status) y observe que %q también usa String.