Enrobage des erreurs (fmt.Errorf)
Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 54 sur 107.
Lorsque les erreurs traversent plusieurs couches de votre application, savoir où une erreur a été générée devient crucial. La fonction fmt.Errorf de Go, avec le verbe %w, vous permet d’envelopper les erreurs, en préservant l’erreur d’origine tout en ajoutant du contexte.
L’enveloppement des erreurs crée une chaîne d’erreurs. Chaque couche peut ajouter des informations sur ce qu’elle essayait de faire lorsque l’erreur s’est produite :
func ReadConfig(filename string) error {
data, err := os.ReadFile(filename)
if err != nil {
return fmt.Errorf("reading config file: %w", err)
}
// traiter les données...
return nil
}Le verbe %w est spécial. Il enveloppe l’erreur d’origine dans la nouvelle. Cela diffère de %v, qui convertit simplement l’erreur en chaîne de caractères et perd l’identité de l’erreur d’origine.
func LoadSettings() error {
err := ReadConfig("settings.json")
if err != nil {
return fmt.Errorf("loading settings: %w", err)
}
return nil
}Lorsque LoadSettings échoue, le message d’erreur affiche la chaîne complète : "loading settings: reading config file: open settings.json: no such file or directory". Chaque couche ajoute du contexte, ce qui facilite grandement le débogage.
L’erreur encapsulée contient toujours l’erreur d’origine. Dans la prochaine leçon, tu apprendras à désencapsuler ces erreurs et à vérifier ce qu’elles contiennent à l’aide de errors.Is() et errors.As().
Défi
FacileConstruisons un système de traitement des commandes qui démontre l'encapsulation des erreurs sur plusieurs niveaux. Vous allez créer une chaîne de fonctions où chaque niveau ajoute du contexte aux erreurs, ce qui facilite le suivi précis de l'origine des problèmes.
Vous organiserez votre code sur deux fichiers :
orders.go: créez la logique de traitement des commandes avec plusieurs niveaux qui encapsulent les erreurs à mesure qu'elles remontent.ValidateItem(itemID string) error- Renvoie une erreur avec le message"item not found"si l'itemID est"INVALID", sinon renvoienilProcessOrder(orderID, itemID string) error- AppelleValidateItem. Si cette fonction renvoie une erreur, encapsulez-la avec le contexte :"processing order [orderID]: %w". Sinon, renvoyeznilSubmitOrder(customerName, orderID, itemID string) error- AppelleProcessOrder. Si cette fonction renvoie une erreur, encapsulez-la avec le contexte :"submitting order for [customerName]: %w". Sinon, renvoyeznilmain.go: lisez les détails de la commande depuis l'entrée, appelezSubmitOrderet affichez le résultat. Si une erreur survient, affichez la chaîne complète des erreurs. En cas de réussite, affichez un message de confirmation.
Implémentez trois fonctions qui forment une chaîne de traitement :
Chaque niveau doit utiliser fmt.Errorf avec le verbe %w pour encapsuler l'erreur du niveau inférieur et construire une chaîne de contexte.
Les entrées suivantes seront fournies :
- Ligne 1 : nom du client
- Ligne 2 : ID de commande
- Ligne 3 : ID de l'article
Affichez le résultat :
- Si une erreur survient :
Error: [full error chain] - En cas de réussite :
Order [orderID] submitted successfully for [customerName]
Par exemple, avec Alice, ORD-123 et INVALID, votre sortie doit être :
Error: submitting order for Alice: processing order ORD-123: item not foundRemarquez comment le message d'erreur affiche la chaîne complète. Vous pouvez suivre le problème depuis la tentative de soumission de niveau supérieur, en passant par le traitement de la commande, jusqu'à l'échec réel de la validation. Chaque niveau a ajouté son propre contexte à l'aide de %w.
Et avec Bob, ORD-456 et ITEM-001, votre sortie doit être :
Order ORD-456 submitted successfully for BobEssayez vous-même
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Lire le nom du client
scanner.Scan()
customerName := scanner.Text()
// Lire l'ID de commande
scanner.Scan()
orderID := scanner.Text()
// Lire l'ID de l'article
scanner.Scan()
itemID := scanner.Text()
// TODO: Appeler SubmitOrder avec les valeurs d'entrée
// TODO: Si une erreur se produit, afficher : Error: [full error chain]
// TODO: If successful, print: Order [orderID] submitted successfully for [customerName]
_ = customerName
_ = orderID
_ = itemID
}
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
1Fondamentaux de la POO en Go
Fichiers externesEspace de travail et modules GoPackages et importsNoms exportés et non exportésIntroduction à la POO en GoStructs comme classesDéfinir des méthodes sur des structsRécepteurs pointeurs ou par valeurInitialisation des structsFonctions constructeursRécapitulatif - Calculatrice simple4Interfaces
Introduction aux interfacesImplémentation impliciteL’interface comme contratInterface vide (any)Assertion de typeCommutation de typeComposition d’interfacesInterfaces Stringer et ErrorRécapitulatif - Calculateur de formes7Encapsulation
Champs exportés vs non exportésEncapsulation au niveau du packageMéthodes Getter et SetterDissimulation de l’information en GoRécapitulatif – Fiches d’étudiants10Génériques (Go 1.18+)
Introduction aux génériquesParamètres de typeContraintes de typeStructures génériquesSolution de contournement pour les méthodes génériquesRécapitulatif - Collection générique2Plongée approfondie dans les types et les structs
Types de base et compositesDéfinitions de types personnalisésTags de structStructs anonymesStructs imbriquésValeurs zéro et valeurs par défautRécapitulatif - Carnet de contacts5La composition plutôt que l’héritage
Pourquoi Go n’a pas d’héritageBases de l’inclusion de structsPromotion des méthodesInclure plusieurs structsInclusion ou agrégationMasquage des méthodes inclusesRécapitulatif : hiérarchie des employés8Gestion des erreurs et POO
L’interface errorTypes d’erreurs personnalisésEnrobage des erreurs (fmt.Errorf)Erreurs sentinelleserrors.Is() et errors.As()Panic, Defer et RecoverRécapitulatif - Analyseur de fichiers11Bibliothèque standard et POO
io.Reader et io.Writersort.InterfaceInterface fmt.Stringerencoding/json avec des structsInterface http.HandlerRécapitulatif - Modèles d’API REST14Modèles de conception – Partie 2
Modèle CommandeModèle AdaptateurModèle DécorateurModèle Méthode modèleModèle ÉtatModèle CompositeMiddleware comme décorateur3Pointeurs et mémoire
Notions de base des pointeurs en GoPointeurs vers des structuresPassage par valeur ou par référenceLa fonction new()Garbage collection en GoRécapitulatif - Constructeur de listes chaînées6Polymorphisme en Go
Polymorphisme via les interfacesDuck typing en GoRègles de satisfaction des interfacesCollections polymorphesInjection de dépendancesRécapitulatif – Processeur de paiements9Concurrence et POO
Bases des GoroutinesCanaux et communicationCanaux tamponnés ou non tamponnésInstruction selectsync.Mutex et sync.RWMutexsync.WaitGroupConception de structures thread-safeRécapitulatif - Pool de workersEntraînez-vous par vous-même : Compilateur Go en ligne