Menu
Coddy logo textTech

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.

quiz iconTestez-vous

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

quiz iconTestez-vous

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

quiz iconTestez-vous

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

challenge icon

Défi

Facile

Construisez 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 à :

  1. Définir trois erreurs sentinelles en utilisant errors.New() :
    • ErrConnectionTimeout avec le message "connection timeout"
    • ErrConnectionRefused avec le message "connection refused"
    • ErrDatabaseNotFound avec le message "database not found"
  2. 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
  3. Analyser la deuxième entrée en la découpant selon les virgules pour obtenir le nom du service et le nombre de tentatives
  4. Créer l'erreur d'origine basée sur le type d'erreur :
    • Si le type d'erreur est "connection_timeout" : utilisez ErrConnectionTimeout
    • Si le type d'erreur est "connection_refused" : utilisez ErrConnectionRefused
    • Si le type d'erreur est "database_not_found" : utilisez ErrDatabaseNotFound
    • Pour tout autre type d'erreur : utilisez errors.New("unknown database error")
  5. Créer une erreur encapsulée au niveau de la base de données en utilisant fmt.Errorf avec %w : "failed to [operation] database [database_name]: %w"
  6. Créer une erreur encapsulée au niveau du service : "[service_name] database operation failed after [retry_count] retries: %w"
  7. Utiliser errors.Is pour 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]"
  8. Afficher la chaîne d'erreurs :
    • "Error Chain:"
    • "Original: [original_error_message]"
    • "Database level: [database_level_error_message]"
    • "Service level: [service_level_error_message]"
  9. 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
	
}
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 Logique & Flux