Menu
Coddy logo textTech

Desenvolver con `errors.As`

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

Mientras que errors.Is te ayuda a identificar valores de error específicos en una cadena, a veces necesitas acceder a los campos y datos reales de un tipo de error personalizado. La función errors.As proporciona esta capacidad al encontrar el primer error en una cadena que coincide con un tipo específico y extraerlo para su inspección.

La función errors.As toma dos parámetros: el error a examinar y un puntero a una variable del tipo de error de destino. Si encuentra un tipo de error coincidente en la cadena, asigna ese error a tu variable y devuelve true:

var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
    fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}

Esto es particularmente potente cuando se trabaja con tipos de error personalizados que contienen contexto adicional. A diferencia de errors.Is, que solo comprueba la igualdad, errors.As extrae la instancia de error real, lo que permite acceder a sus campos y métodos. Esto hace que el manejo de errores sea más sofisticado e informativo en aplicaciones complejas.

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 manejo de errores de API que utilice errors.As para extraer y examinar tipos de errores personalizados de cadenas de errores envueltos. Este desafío demuestra cómo usar errors.As para acceder a los campos y datos de tipos de errores personalizados específicos, incluso cuando han sido envueltos con contexto adicional.

Recibirás dos entradas:

  • Una cadena que contiene los detalles de la solicitud de la API en el formato "endpoint,method,error_code,error_field" (por ejemplo, "/users,POST,400,email")
  • Una cadena que contiene el contexto del sistema en el formato "service_name,request_id" (por ejemplo, "UserAPI,req_12345")

Tu tarea es:

  1. Crear un tipo de error personalizado llamado struct APIError con tres campos:
    • Code (int) - el código de estado HTTP
    • Field (string) - el campo que causó el error
    • Message (string) - una descripción del error
  2. Implementar el método Error() string para APIError que devuelva: "API error [code]: [message] (field: [field])"
  3. Analizar la primera entrada dividiéndola por comas para obtener el endpoint, method, error code y error field
  4. Analizar la segunda entrada dividiéndola por comas para obtener el service name y request ID
  5. Convertir la cadena del código de error en un entero
  6. Crear una instancia de APIError basada en el código de error:
    • Si el código es 400: mensaje "invalid request data"
    • Si el código es 401: mensaje "authentication required"
    • Si el código es 404: mensaje "resource not found"
    • Si el código es 500: mensaje "internal server error"
    • Para cualquier otro código: mensaje "unknown error"
  7. Crear un error envuelto a nivel de endpoint usando fmt.Errorf con %w: "[method] [endpoint] failed: %w"
  8. Crear un error envuelto a nivel de servicio: "[service_name] request [request_id] failed: %w"
  9. Usar errors.As para extraer el APIError de la cadena de errores envueltos y mostrar el resultado de la extracción:
    • Si la extracción tiene éxito: "API error extracted successfully"
    • Si la extracción falla: "Failed to extract API error"
  10. Si la extracción tuvo éxito, mostrar los detalles del error extraído:
    • "Extracted Error Details:"
    • "Code: [code]"
    • "Field: [field]"
    • "Message: [message]"
    • "Full error: [full_error_message_from_Error_method]"
  11. Mostrar la cadena de errores completa:
    • "Error Chain:"
    • "Original: [original_api_error_message]"
    • "Endpoint level: [endpoint_level_error_message]"
    • "Service level: [service_level_error_message]"
  12. Mostrar un análisis final:
    • "Error Analysis:"
    • "Service: [service_name]"
    • "Request ID: [request_id]"
    • "Endpoint: [method] [endpoint]"
    • "HTTP Status: [code]"
    • "Problem Field: [field]"
    • "Error Category: [error_category]" donde error_category es "Client Error" para códigos 400-499, "Server Error" para códigos 500-599, o "Unknown" para otros códigos

Usa el paquete strings para dividir las cadenas de entrada por comas, el paquete strconv para convertir la cadena del código de error en un entero, el paquete errors para errors.As, y el paquete fmt para envolver errores. Este desafío demuestra cómo errors.As te permite acceder a los campos y métodos específicos de tipos de errores personalizados dentro de cadenas de errores envueltos, permitiendo un manejo y análisis de errores sofisticado.

Hoja de referencia

La función errors.As extrae tipos de error específicos de las cadenas de errores, permitiendo el acceso a campos y métodos de error personalizados.

errors.As toma dos parámetros: el error a examinar y un puntero a una variable del tipo de error de destino:

var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
    fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}

A diferencia de errors.Is, que solo comprueba la igualdad, errors.As extrae la instancia de error real, lo que permite el acceso a sus campos y métodos para un manejo de errores más sofisticado.

Pruébalo tú mismo

package main

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

func main() {
	// Leer entrada
	var apiDetails string
	var systemContext string
	fmt.Scanln(&apiDetails)
	fmt.Scanln(&systemContext)
	
	// Analizar entradas
	apiParts := strings.Split(apiDetails, ",")
	endpoint := apiParts[0]
	method := apiParts[1]
	errorCodeStr := apiParts[2]
	errorField := apiParts[3]
	
	contextParts := strings.Split(systemContext, ",")
	serviceName := contextParts[0]
	requestID := contextParts[1]
	
	// Convertir el código de error a entero
	errorCode, _ := strconv.Atoi(errorCodeStr)
	
	// TODO: Escribe tu código a continuación
	// 1. Crear la estructura APIError con los campos Code, Field, Message
	// 2. Implementar el método Error() para APIError
	// 3. Crear una instancia de APIError basada en el código de error
	// 4. Crear errores envueltos (a nivel de endpoint y a nivel de servicio)
	// 5. Usar errors.As para extraer APIError de la cadena de errores envueltos
	// 6. Mostrar el resultado de la extracción y los detalles del error
	// 7. Mostrar la cadena de errores y el análisis final
	
}
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