Vai al contenuto
eLearner.app
Modulo 2 · Lezione 5 di 510/50 nel corso~12 min
Lezioni del modulo (5/5)

Errori: il pattern `if err != nil`

In Go gli errori sono valori, non eccezioni. Una funzione che può fallire ritorna l'errore come ultimo valore, e chi chiama lo controlla esplicitamente. È esplicito, prevedibile, facile da testare — il prezzo è un po' più di verbosità.

L'interfaccia error

error è una piccola interfaccia integrata nel linguaggio:

Go
type error interface {
    Error() string
}

Qualunque tipo che implementa Error() string è un error.

Il pattern fondamentale

Go
v, err := operazione()
if err != nil {
    // gestisci o propaga
    return err
}
// usa v

Lo vedrai migliaia di volte: è il codice idiomatico per ogni chiamata fallibile. Non sentirti in colpa per la ripetizione — è una feature, non un bug.

Costruire errori: errors.New e fmt.Errorf

Go
import (
    "errors"
    "fmt"
)

err1 := errors.New("file mancante")
err2 := fmt.Errorf("apertura %q fallita: permesso negato", path)

fmt.Errorf è perfetto quando vuoi includere variabili nel messaggio.

Wrapping con %w

Per propagare un errore aggiungendo contesto SENZA perdere l'originale:

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

%w "avvolge" l'errore originale, recuperabile più tardi con errors.Is (uguaglianza per sentinel) o errors.As (per tipo concreto):

Go
if errors.Is(err, os.ErrNotExist) {
    // file inesistente, gestione speciale
}

Sentinel errors

Sono errori esportati come variabili, usati per confronti con errors.Is:

Go
var ErrNotFound = errors.New("non trovato")

func find(id int) (Item, error) {
    // ...
    return Item{}, ErrNotFound
}

// chiamante:
if errors.Is(err, ErrNotFound) { ... }

panic e recover (cenno)

panic esiste in Go ma è riservato a errori irrecuperabili (es. bug, invariants violati), non al normale controllo di flusso. Lo approfondiremo nel modulo Funzioni con defer/recover. Per ora: non usarlo al posto del pattern if err != nil.

Prova tu

Esercizio#go.m2.l5.e1
Tentativi: 0Caricamento…

Gestisci l'errore di strconv.Atoi: se err != nil, stampalo e ritorna; altrimenti stampa n.

Caricamento editor…
Mostra suggerimento

Il pattern canonico: check `err != nil`, log/return, poi usa `n`.

Soluzione disponibile dopo 3 tentativi

Esercizio#go.m2.l5.e2
Tentativi: 0Caricamento…

Implementa safeDiv: se b == 0 ritorna 0 e un errors.New('divisione per zero'); altrimenti a/b e nil.

Caricamento editor…
Mostra suggerimento

Controlla `b == 0` PRIMA della divisione per evitare il panic da run-time.

Soluzione disponibile dopo 3 tentativi

Quiz#go.m2.l5.e3
Pronto

Quale è il pattern idiomatico per gestire un errore in Go?

Go
v, err := f()
// poi?
Opzioni di risposta

Recap

  • error è un'interfaccia con un metodo Error() string.
  • Pattern canonico: v, err := f(); if err != nil { return err }.
  • Costruisci errori con errors.New(msg) o fmt.Errorf("ctx: %w", err).
  • Usa %w per wrapping e errors.Is / errors.As per ispezionare la catena.
  • panic solo per errori irrecuperabili, NON per il normale controllo di flusso.