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.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Desafío
FácilConstruye 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:
- Crear un tipo de error personalizado llamado struct
APIErrorcon tres campos:Code(int) - el código de estado HTTPField(string) - el campo que causó el errorMessage(string) - una descripción del error
- Implementar el método
Error() stringparaAPIErrorque devuelva:"API error [code]: [message] (field: [field])" - Analizar la primera entrada dividiéndola por comas para obtener el endpoint, method, error code y error field
- Analizar la segunda entrada dividiéndola por comas para obtener el service name y request ID
- Convertir la cadena del código de error en un entero
- Crear una instancia de
APIErrorbasada 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"
- Si el código es 400: mensaje
- Crear un error envuelto a nivel de endpoint usando
fmt.Errorfcon%w:"[method] [endpoint] failed: %w" - Crear un error envuelto a nivel de servicio:
"[service_name] request [request_id] failed: %w" - Usar
errors.Aspara extraer elAPIErrorde 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"
- Si la extracción tiene éxito:
- 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]"
- 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]"
- 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
}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
1Flujo de control avanzado
Switch con `fallthrough`Salir de bucles anidadosContinuar un bucle específicoLa sentencia `goto`Repaso: Control de bucles avanzado4Proyecto: Lista de tareas sencilla
Configuración del proyectoAñadir una tarea7Manejo de errores a fondo
Tipos de error personalizadosEnvolver errores con `%w`Desenvolver con `errors.Is`Desenvolver con `errors.As`Entendiendo `panic`Uso de `recover`Repaso - División segura2Estructuras y Métodos
Definición de métodos en estructurasReceptores de valorReceptores de punteroElegir receptoresMétodos vs FuncionesResumen - Comportamiento de estructuras5Mapas en profundidad
Mapas de StructsPunteros como valores de MapVerificación de Maps NilComparación de MapsResumen - Contador de frecuencia de palabras3Interfaces (Conceptos básicos)
¿Qué es una interfaz?Definir una interfazImplementar una interfazUso de tipos de interfazInterfaz vacíaAserciones de tipoType SwitchResumen: Formas y comportamientos