Menu
Coddy logo textTech

Errori sentinella

Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 55 di 107.

Un errore sentinella è una variabile di errore predefinita a livello di pacchetto che rappresenta una specifica condizione di errore. A differenza della creazione di nuovi errori ogni volta con errors.New, gli errori sentinella vengono dichiarati una sola volta e riutilizzati in tutto il codice.

Definisci gli errori sentinella come variabili a livello di pacchetto, in genere con nomi che iniziano con Err:

package user

import "errors"

var (
    ErrNotFound     = errors.New("user not found")
    ErrInvalidEmail = errors.New("invalid email address")
    ErrDuplicate    = errors.New("user already exists")
)

Le funzioni restituiscono questi errori predefiniti quando si verificano determinate condizioni:

func FindUser(id int) (*User, error) {
    user, exists := users[id]
    if !exists {
        return nil, ErrNotFound
    }
    return user, nil
}

Il vantaggio degli errori sentinella è che i chiamanti possono verificare condizioni di errore specifiche confrontando direttamente i valori degli errori:

user, err := FindUser(42)
if err == ErrNotFound {
    fmt.Println("Creating new user...")
} else if err != nil {
    fmt.Println("Unexpected error:", err)
}

La libreria standard di Go usa ampiamente gli errori sentinella. Per esempio, io.EOF segnala la fine dell'input e sql.ErrNoRows indica un risultato vuoto della query. Questo schema crea un contratto chiaro tra i pacchetti e chi li usa riguardo agli errori che ci si può aspettare.

Tuttavia, i semplici controlli di uguaglianza non funzionano quando gli errori vengono avvolti. Nella prossima lezione imparerai come errors.Is() risolve questo problema controllando l'intera catena di errori.

challenge icon

Sfida

Facile

Costruiamo un sistema di gestione dell'inventario che usa errori sentinella per comunicare condizioni di errore specifiche. Definirai variabili di errore a livello di package che i chiamanti possono controllare per gestire in modo appropriato i diversi casi.

Organizzerai il codice in due file:

  • inventory.go: crea un sistema di inventario con errori sentinella predefiniti per i casi di errore più comuni.

    Definisci tre errori sentinella a livello di package:

    • ErrItemNotFound con il messaggio "item not found in inventory"
    • ErrOutOfStock con il messaggio "item is out of stock"
    • ErrInsufficientQuantity con il messaggio "insufficient quantity available"

    Crea una struct Inventory che contiene una mappa dei nomi degli articoli e delle relative quantità. Implementa questi metodi:

    • NewInventory() *Inventory - crea un inventario vuoto
    • AddItem(name string, quantity int) - aggiunge o aggiorna la quantità di un articolo
    • GetQuantity(name string) (int, error) - restituisce la quantità di un articolo oppure ErrItemNotFound se non esiste
    • Purchase(name string, quantity int) error - tenta di acquistare gli articoli. Restituisci ErrItemNotFound se l'articolo non esiste, ErrOutOfStock se la quantità attuale è zero oppure ErrInsufficientQuantity se la quantità richiesta supera la disponibilità. In caso di successo, riduci la quantità nell'inventario e restituisci nil.
  • main.go: leggi le operazioni sull'inventario dall'input e mostra come i chiamanti possono controllare errori sentinella specifici usando il confronto diretto di uguaglianza.

    Leggi dall'input il nome dell'articolo e la quantità da acquistare. Crea un inventario, aggiungi l'articolo "laptop" con quantità 5, quindi tenta l'acquisto. In base all'errore restituito, stampa un messaggio specifico che mostri quale errore sentinella si è verificato.

Verranno forniti i seguenti input:

  • Riga 1: nome dell'articolo da acquistare
  • Riga 2: quantità da acquistare

Gestisci il risultato controllando quale errore specifico è stato restituito:

  • Se err == ErrItemNotFound: stampa Error: Item '[name]' does not exist in our inventory
  • Se err == ErrOutOfStock: stampa Error: Item '[name]' is currently out of stock
  • Se err == ErrInsufficientQuantity: stampa Error: Cannot purchase [quantity] units of '[name]' - not enough in stock
  • In caso di successo: stampa Successfully purchased [quantity] units of '[name]'

Per esempio, dati laptop e 3, l'output dovrebbe essere:

Successfully purchased 3 units of 'laptop'

E dati phone e 2, l'output dovrebbe essere:

Error: Item 'phone' does not exist in our inventory

E dati laptop e 10, l'output dovrebbe essere:

Error: Cannot purchase 10 units of 'laptop' - not enough in stock

Provalo tu

package main

import (
	"fmt"
)

func main() {
	// Leggi l'input
	var itemName string
	var quantity int
	fmt.Scanln(&itemName)
	fmt.Scanln(&quantity)

	// Crea l'inventario e aggiungi "laptop" con quantità 5
	inv := NewInventory()
	inv.AddItem("laptop", 5)

	// TODO: Prova ad acquistare l'articolo
	// Chiama inv.Purchase(itemName, quantity)

	// TODO: Controlla quale specifico errore sentinella è stato restituito usando un confronto diretto di uguaglianza
	// Usa istruzioni if/else if per verificare:
	// - err == ErrItemNotFound
	// - err == ErrOutOfStock
	// - err == ErrInsufficientQuantity
	// - err == nil (operazione riuscita)

	// TODO: Stampa il messaggio appropriato in base all'errore
	// Se ErrItemNotFound: fmt.Printf("Error: Item '%s' does not exist in our inventory\n", itemName)
	// Se ErrOutOfStock: fmt.Printf("Error: Item '%s' is currently out of stock\n", itemName)
	// Se ErrInsufficientQuantity: fmt.Printf("Error: Cannot purchase %d units of '%s' - not enough in stock\n", quantity, itemName)
	// Se l'operazione riesce: fmt.Printf("Successfully purchased %d units of '%s'\n", quantity, itemName)
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Go online