Menu
Coddy logo textTech

Desenvolver con `errors.Is`

Parte de la sección Lógica y Flujo del Journey de GO de Coddy — lección 40 de 68.

Al trabajar con errores envueltos, necesitas una forma de comprobar si un error específico existe en cualquier lugar de la cadena de errores. La función errors.Is proporciona exactamente esta capacidad, permitiéndote identificar errores centinela incluso cuando han sido envueltos varias veces.

La función errors.Is toma dos parámetros: el error que deseas examinar y el error de destino que estás buscando. Devuelve true si el error de destino se encuentra en cualquier lugar de la cadena de errores:

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")
}

Esta es la forma moderna y recomendada de comprobar errores específicos en Go. A diferencia de la comparación de cadenas o las comprobaciones de igualdad directa, errors.Is funciona correctamente con errores envueltos y sigue la cadena de errores para encontrar coincidencias. Esto hace que el manejo de errores sea robusto y confiable, incluso cuando los errores pasan a través de múltiples capas de su aplicación.

quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

challenge icon

Desafío

Fácil

Construye un sistema de monitoreo de conexión a base de datos que utilice errors.Is para identificar errores de conexión específicos en cadenas de errores envueltos (wrapped errors). Este desafío demuestra cómo usar errors.Is para detectar errores centinela incluso cuando han sido envueltos con contexto adicional a través de múltiples capas de la aplicación.

Recibirás dos entradas:

  • Una cadena que contiene detalles de la operación de la base de datos en el formato "database_name,operation,error_type" (por ejemplo, "users_db,connect,connection_timeout")
  • Una cadena que contiene el contexto de la aplicación en el formato "service_name,retry_count" (por ejemplo, "AuthService,3")

Tu tarea es:

  1. Definir tres errores centinela usando errors.New():
    • ErrConnectionTimeout con el mensaje "connection timeout"
    • ErrConnectionRefused con el mensaje "connection refused"
    • ErrDatabaseNotFound con el mensaje "database not found"
  2. Analizar la primera entrada dividiéndola por comas para obtener el nombre de la base de datos, la operación y el tipo de error
  3. Analizar la segunda entrada dividiéndola por comas para obtener el nombre del servicio y el número de reintentos
  4. Crear el error original basado en el tipo de error:
    • Si el tipo de error es "connection_timeout": usa ErrConnectionTimeout
    • Si el tipo de error es "connection_refused": usa ErrConnectionRefused
    • Si el tipo de error es "database_not_found": usa ErrDatabaseNotFound
    • Para cualquier otro tipo de error: usa errors.New("unknown database error")
  5. Crear un error envuelto a nivel de base de datos usando fmt.Errorf con %w: "failed to [operation] database [database_name]: %w"
  6. Crear un error envuelto a nivel de servicio: "[service_name] database operation failed after [retry_count] retries: %w"
  7. Usar errors.Is para verificar si el error envuelto final coincide con cada error centinela y mostrar los resultados:
    • "Checking for connection timeout: [true/false]"
    • "Checking for connection refused: [true/false]"
    • "Checking for database not found: [true/false]"
  8. Mostrar la cadena de errores:
    • "Error Chain:"
    • "Original: [original_error_message]"
    • "Database level: [database_level_error_message]"
    • "Service level: [service_level_error_message]"
  9. Mostrar el análisis del error:
    • "Error Analysis:"
    • "Database: [database_name]"
    • "Operation: [operation]"
    • "Service: [service_name]"
    • "Retries: [retry_count]"
    • "Error type detected: [detected_error_type]" donde detected_error_type es uno de "Connection Timeout", "Connection Refused", "Database Not Found", o "Unknown Error"

Usa el paquete strings para dividir las cadenas de entrada por comas, el paquete errors para los errores centinela y errors.Is, y el paquete fmt para envolver los errores. Este desafío demuestra cómo errors.Is proporciona una identificación de errores robusta que funciona correctamente con errores envueltos, lo que lo hace esencial para un manejo de errores confiable en aplicaciones complejas.

Hoja de referencia

La función errors.Is comprueba si un error específico existe en cualquier lugar de una cadena de errores, incluso cuando está envuelto varias veces:

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 toma dos parámetros: el error a examinar y el error de destino a buscar. Devuelve true si el error de destino se encuentra en cualquier lugar de la cadena de errores.

Esta es la forma moderna y recomendada de comprobar errores específicos en Go, ya que funciona correctamente con errores envueltos, a diferencia de la comparación de cadenas o las comprobaciones de igualdad directa.

Pruébalo tú mismo

package main

import (
	"errors"
	"fmt"
	"strings"
)

func main() {
	// Leer entrada
	var dbOperation string
	var appContext string
	fmt.Scanln(&dbOperation)
	fmt.Scanln(&appContext)
	
	// Analizar entradas
	dbParts := strings.Split(dbOperation, ",")
	databaseName := dbParts[0]
	operation := dbParts[1]
	errorType := dbParts[2]
	
	contextParts := strings.Split(appContext, ",")
	serviceName := contextParts[0]
	retryCount := contextParts[1]
	
	// TODO: Escribe tu código a continuación
	// 1. Definir los tres errores centinela usando errors.New()
	// 2. Crear el error original basado en el tipo de error
	// 3. Crear un error envuelto a nivel de base de datos usando fmt.Errorf con %w
	// 4. Crear un error envuelto a nivel de servicio
	// 5. Usar errors.Is para verificar cada error centinela
	// 6. Mostrar los resultados y la cadena de errores
	
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Lógica y Flujo