Menu
Coddy logo textTech

Erreurs sentinelles

Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 55 sur 107.

Une erreur sentinelle est une variable d’erreur prédéfinie au niveau du package qui représente une condition d’erreur spécifique. Contrairement à la création de nouvelles erreurs à chaque fois avec errors.New, les erreurs sentinelles sont déclarées une seule fois et réutilisées dans tout votre code.

Vous définissez les erreurs sentinelles en tant que variables au niveau du package, généralement avec des noms commençant par Err :

package user

import "errors"

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

Les fonctions renvoient ces erreurs prédéfinies lorsque des conditions spécifiques surviennent :

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

La puissance des erreurs sentinelles réside dans le fait que les appelants peuvent vérifier des conditions d'erreur spécifiques en comparant directement les valeurs d'erreur :

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

La bibliothèque standard de Go utilise intensivement les erreurs sentinelles. Par exemple, io.EOF signale la fin de l'entrée, et sql.ErrNoRows indique un résultat de requête vide. Ce modèle crée un contrat clair entre les packages et leurs utilisateurs sur les erreurs à attendre.

Cependant, les vérifications d'égalité simples échouent lorsque les erreurs sont enveloppées. Dans la prochaine leçon, vous apprendrez comment errors.Is() résout ce problème en vérifiant toute la chaîne d'erreurs.

challenge icon

Défi

Facile

Construisons un système de gestion des stocks qui utilise des erreurs sentinelles pour communiquer des conditions d’échec spécifiques. Vous définirez des variables d’erreur au niveau du package que les appelants pourront vérifier afin de gérer correctement différents scénarios.

Vous organiserez votre code sur deux fichiers :

  • inventory.go : créez un système d’inventaire avec des erreurs sentinelles prédéfinies pour les cas d’échec courants.

    Définissez trois erreurs sentinelles au niveau du package :

    • ErrItemNotFound avec le message "item not found in inventory"
    • ErrOutOfStock avec le message "item is out of stock"
    • ErrInsufficientQuantity avec le message "insufficient quantity available"

    Créez une structure Inventory qui contient une map associant les noms des articles à leurs quantités. Implémentez ces méthodes :

    • NewInventory() *Inventory - crée un inventaire vide
    • AddItem(name string, quantity int) - ajoute ou met à jour la quantité d’un article
    • GetQuantity(name string) (int, error) - renvoie la quantité d’un article, ou ErrItemNotFound s’il n’existe pas
    • Purchase(name string, quantity int) error - tente d’acheter des articles. Renvoie ErrItemNotFound si l’article n’existe pas, ErrOutOfStock si la quantité actuelle est égale à zéro, ou ErrInsufficientQuantity si la quantité demandée dépasse le stock disponible. En cas de réussite, diminuez l’inventaire et renvoyez nil.
  • main.go : lisez les opérations d’inventaire depuis l’entrée et montrez comment les appelants peuvent vérifier des erreurs sentinelles spécifiques à l’aide d’une comparaison directe d’égalité.

    Lisez le nom de l’article et la quantité à acheter depuis l’entrée. Créez un inventaire, ajoutez l’article "laptop" avec une quantité de 5, puis tentez l’achat. En fonction de l’erreur renvoyée, affichez un message spécifique montrant que vous avez identifié l’erreur sentinelle qui s’est produite.

Les entrées suivantes seront fournies :

  • Ligne 1 : nom de l’article à acheter
  • Ligne 2 : quantité à acheter

Gérez le résultat en vérifiant quelle erreur spécifique a été renvoyée :

  • Si err == ErrItemNotFound : affichez Error: Item '[name]' does not exist in our inventory
  • Si err == ErrOutOfStock : affichez Error: Item '[name]' is currently out of stock
  • Si err == ErrInsufficientQuantity : affichez Error: Cannot purchase [quantity] units of '[name]' - not enough in stock
  • En cas de réussite : affichez Successfully purchased [quantity] units of '[name]'

Par exemple, avec laptop et 3, votre sortie devrait être :

Successfully purchased 3 units of 'laptop'

Et avec phone et 2, votre sortie devrait être :

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

Et avec laptop et 10, votre sortie devrait être :

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

Essayez vous-même

package main

import (
	"fmt"
)

func main() {
	// Lire l'entrée
	var itemName string
	var quantity int
	fmt.Scanln(&itemName)
	fmt.Scanln(&quantity)

	// Créer l'inventaire et ajouter "laptop" avec une quantité de 5
	inv := NewInventory()
	inv.AddItem("laptop", 5)

	// TODO: Tenter d'acheter l'article
	// Appeler inv.Purchase(itemName, quantity)

	// TODO: Vérifier quelle erreur sentinelle spécifique a été retournée en utilisant une comparaison d'égalité directe
	// Utiliser des instructions if/else if pour vérifier :
	// - err == ErrItemNotFound
	// - err == ErrOutOfStock
	// - err == ErrInsufficientQuantity
	// - err == nil (succès)

	// TODO: Afficher le message approprié en fonction de l'erreur
	// Si ErrItemNotFound: fmt.Printf("Error: Item '%s' does not exist in our inventory\n", itemName)
	// Si ErrOutOfStock: fmt.Printf("Error: Item '%s' is currently out of stock\n", itemName)
	// Si ErrInsufficientQuantity: fmt.Printf("Error: Cannot purchase %d units of '%s' - not enough in stock\n", quantity, itemName)
	// Si succès: fmt.Printf("Successfully purchased %d units of '%s'\n", quantity, itemName)
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Go en ligne