Désenvelopper avec `errors.Is`
Fait partie de la section Logique & Flux du Journey GO de Coddy — leçon 40 sur 68.
Lorsque vous travaillez avec des erreurs enveloppées, vous avez besoin d'un moyen de vérifier si une erreur spécifique existe n'importe où dans la chaîne d'erreurs. La fonction errors.Is offre précisément cette capacité, vous permettant d'identifier des erreurs sentinelles même lorsqu'elles ont été enveloppées plusieurs fois.
La fonction errors.Is prend deux paramètres : l'erreur que vous souhaitez examiner et l'erreur cible que vous recherchez. Elle retourne true si l'erreur cible est trouvée n'importe où dans la chaîne d'erreurs :
var ErrNotFound = errors.New("not found")
wrappedErr := fmt.Errorf("failed to load user: %w", ErrNotFound)
if errors.Is(wrappedErr, ErrNotFound) {
fmt.Println("This is a not found error")
}C'est la méthode moderne et recommandée pour vérifier des erreurs spécifiques en Go. Contrairement à la comparaison de chaînes ou aux vérifications d'égalité directe, errors.Is fonctionne correctement avec les erreurs enveloppées et suit la chaîne d'erreurs pour trouver des correspondances. Cela rend votre gestion des erreurs robuste et fiable, même lorsque les erreurs passent par plusieurs couches de votre application.
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Défi
FacileConstruisez un système de surveillance de connexion à une base de données qui utilise errors.Is pour identifier des erreurs de connexion spécifiques dans des chaînes d'erreurs encapsulées (wrapped). Ce défi démontre comment utiliser errors.Is pour détecter des erreurs sentinelles même lorsqu'elles ont été encapsulées avec un contexte supplémentaire à travers plusieurs couches applicatives.
Vous recevrez deux entrées :
- Une chaîne contenant les détails de l'opération de base de données au format
"database_name,operation,error_type"(par exemple,"users_db,connect,connection_timeout") - Une chaîne contenant le contexte de l'application au format
"service_name,retry_count"(par exemple,"AuthService,3")
Votre tâche consiste à :
- Définir trois erreurs sentinelles en utilisant
errors.New():ErrConnectionTimeoutavec le message"connection timeout"ErrConnectionRefusedavec le message"connection refused"ErrDatabaseNotFoundavec le message"database not found"
- Analyser la première entrée en la découpant selon les virgules pour obtenir le nom de la base de données, l'opération et le type d'erreur
- Analyser la deuxième entrée en la découpant selon les virgules pour obtenir le nom du service et le nombre de tentatives
- Créer l'erreur d'origine basée sur le type d'erreur :
- Si le type d'erreur est
"connection_timeout": utilisezErrConnectionTimeout - Si le type d'erreur est
"connection_refused": utilisezErrConnectionRefused - Si le type d'erreur est
"database_not_found": utilisezErrDatabaseNotFound - Pour tout autre type d'erreur : utilisez
errors.New("unknown database error")
- Si le type d'erreur est
- Créer une erreur encapsulée au niveau de la base de données en utilisant
fmt.Errorfavec%w:"failed to [operation] database [database_name]: %w" - Créer une erreur encapsulée au niveau du service :
"[service_name] database operation failed after [retry_count] retries: %w" - Utiliser
errors.Ispour vérifier si l'erreur encapsulée finale correspond à chaque erreur sentinelle et afficher les résultats :"Checking for connection timeout: [true/false]""Checking for connection refused: [true/false]""Checking for database not found: [true/false]"
- Afficher la chaîne d'erreurs :
"Error Chain:""Original: [original_error_message]""Database level: [database_level_error_message]""Service level: [service_level_error_message]"
- Afficher l'analyse de l'erreur :
"Error Analysis:""Database: [database_name]""Operation: [operation]""Service: [service_name]""Retries: [retry_count]""Error type detected: [detected_error_type]"où detected_error_type est l'un des suivants : "Connection Timeout", "Connection Refused", "Database Not Found", ou "Unknown Error"
Utilisez le package strings pour découper les chaînes d'entrée sur les virgules, le package errors pour les erreurs sentinelles et errors.Is, et le package fmt pour l'encapsulation d'erreurs. Ce défi démontre comment errors.Is fournit une identification d'erreur robuste qui fonctionne correctement avec les erreurs encapsulées, ce qui le rend essentiel pour une gestion d'erreurs fiable dans des applications complexes.
Aide-mémoire
La fonction errors.Is vérifie si une erreur spécifique existe n'importe où dans une chaîne d'erreurs, même lorsqu'elle est enveloppée plusieurs fois :
var ErrNotFound = errors.New("not found")
wrappedErr := fmt.Errorf("failed to load user: %w", ErrNotFound)
if errors.Is(wrappedErr, ErrNotFound) {
fmt.Println("This is a not found error")
}errors.Is prend deux paramètres : l'erreur à examiner et l'erreur cible à trouver. Elle renvoie true si l'erreur cible est trouvée n'importe où dans la chaîne d'erreurs.
C'est la méthode moderne et recommandée pour vérifier des erreurs spécifiques en Go, car elle fonctionne correctement avec les erreurs enveloppées, contrairement à la comparaison de chaînes de caractères ou aux vérifications d'égalité directe.
Essayez vous-même
package main
import (
"errors"
"fmt"
"strings"
)
func main() {
// Lire l'entrée
var dbOperation string
var appContext string
fmt.Scanln(&dbOperation)
fmt.Scanln(&appContext)
// Analyser les entrées
dbParts := strings.Split(dbOperation, ",")
databaseName := dbParts[0]
operation := dbParts[1]
errorType := dbParts[2]
contextParts := strings.Split(appContext, ",")
serviceName := contextParts[0]
retryCount := contextParts[1]
// TODO: Écrivez votre code ci-dessous
// 1. Définir les trois erreurs sentinelles en utilisant errors.New()
// 2. Créer l'erreur d'origine basée sur le type d'erreur
// 3. Créer l'erreur enveloppée au niveau de la base de données en utilisant fmt.Errorf avec %w
// 4. Créer l'erreur enveloppée au niveau du service
// 5. Utiliser errors.Is pour vérifier chaque erreur sentinelle
// 6. Afficher les résultats et la chaîne d'erreurs
}Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Logique & Flux
1Structures de contrôle avancées
Switch avec `fallthrough`Sortir de boucles imbriquéesContinuer une boucle spécifiqueL'instruction `goto`Récapitulatif - Contrôle de boucle avancé4Projet : Liste de tâches simple
Configuration du projetAjouter une tâche7Gestion des erreurs en profondeur
Types d'erreurs personnalisésEnvelopper des erreurs avec `%w`Désenvelopper avec `errors.Is`Désenvelopper avec `errors.As`Comprendre `panic`Utiliser `recover`Récapitulatif - Division sécurisée2Structures et Méthodes
Définir des méthodes sur des structuresReceveurs par valeurReceveurs par pointeurChoisir les receveursMéthodes vs FonctionsRécapitulatif - Comportement des structures5Les Maps en profondeur
Maps de StructsPointeurs comme valeurs de MapTester les Maps NilComparer des MapsRécapitulatif - Compteur de fréquence de mots3Interfaces (Les bases)
Qu'est-ce qu'une Interface ?Définir une InterfaceImplémenter une InterfaceUtiliser les types d'InterfaceInterface videAssertions de typeType SwitchRécapitulatif - Formes et comportements