Vai al contenuto
eLearner.app
Modulo 8 · Lezione 1 di 536/50 nel corso~10 min
Lezioni del modulo (1/5)

`fmt` avanzato

Il pacchetto fmt è la porta d'ingresso di tutti gli I/O testuali in Go. Conoscerlo bene significa scrivere log leggibili, errori informativi e formattare valori in modo idiomatico senza ricorrere a librerie esterne.

Le quattro famiglie

fmt espone funzioni in quattro famiglie, distinte dal prefisso:

  • Print* → scrive su os.Stdout (Print, Println, Printf).
  • Fprint* → scrive su un io.Writer qualsiasi (Fprintln(os.Stderr, ...), Fprintf(file, ...)).
  • Sprint* → restituisce una stringa senza stampare (Sprintf, Sprintln).
  • Errorf → costruisce un error formattato.
Go
fmt.Println("hello")                       // stdout
fmt.Fprintln(os.Stderr, "boom")            // stderr
s := fmt.Sprintf("[%d]", 42)               // "[42]"
err := fmt.Errorf("parse %q: %w", in, base) // error wrappato

La differenza fra Print e Println è solo lo spazio fra gli argomenti e il newline finale: Println aggiunge sempre \n, Print no, Printf segue il formato.

Verbi principali

VerboCosa fa
%vValore di default (richiama String() se implementato).
%+vStruct con nomi dei campi.
%#vSintassi Go (utile per debug e snapshot).
%TTipo dinamico del valore.
%dIntero in base 10.
%b %o %x %XBinario, ottale, esadecimale (minuscolo/maiuscolo).
%f %e %gFloating point: fisso, esponenziale, compatto.
%sStringa (o error/Stringer).
%qStringa quotata stile Go (escape inclusi).
%cCarattere Unicode (rune).
%pPuntatore in esadecimale.
%wWrap di error (solo dentro Errorf).
Go
type Point struct{ X, Y int }
p := Point{1, 2}
fmt.Printf("%v\n", p)   // {1 2}
fmt.Printf("%+v\n", p)  // {X:1 Y:2}
fmt.Printf("%#v\n", p)  // main.Point{X:1, Y:2}
fmt.Printf("%T\n", p)   // main.Point

Larghezza, precisione, flag

I verbi numerici e di stringa accettano larghezza e precisione:

  • %6d → larghezza minima 6, padding di spazi a sinistra.
  • %-6d → larghezza 6, padding a destra (flag -).
  • %06d → larghezza 6, padding con 0 (flag 0).
  • %.2f → precisione 2 cifre decimali.
  • %8.2f → larghezza 8, precisione 2.
Go
fmt.Printf("|%6d|\n", 42)    // |    42|
fmt.Printf("|%-6d|\n", 42)   // |42    |
fmt.Printf("|%06d|\n", 42)   // |000042|
fmt.Printf("|%8.2f|\n", 3.14)// |    3.14|

Per tabelle allineate, larghezza fissa + %-...s per le colonne testuali è il pattern più semplice prima di passare a text/tabwriter.

%w e wrapping degli errori

%w è speciale: funziona solo dentro fmt.Errorf e conserva l'errore originale nella catena, in modo che errors.Is ed errors.As possano risalirla.

Go
if _, err := os.Open(path); err != nil {
    return fmt.Errorf("read config %q: %w", path, err)
}

Usare %v invece di %w stampa il messaggio dell'errore ma rompe la catena: niente unwrap, niente errors.Is. Regola: se vuoi che il chiamante possa distinguere il tipo o l'identità dell'errore, usa %w (uno solo per Errorf).

Esercizi

Esercizio#go.m8.l1.e1
Tentativi: 0Caricamento…

Usa fmt.Sprintf per formattare la stringa '[42]' a partire dall'intero 42, poi stampala.

Caricamento editor…

Soluzione disponibile dopo 3 tentativi

Esercizio#go.m8.l1.e2
Tentativi: 0Caricamento…

Stampa la struct p con il verbo %+v (deve includere i nomi dei campi).

Caricamento editor…

Soluzione disponibile dopo 3 tentativi

Quiz#go.m8.l1.e3
Pronto

Quale verbo, usato in fmt.Errorf, preserva la catena di errori per errors.Is/As?

Go
err := fmt.Errorf("read %q: ???", path, base)
Opzioni di risposta