Menu
Coddy logo textTech

Unwrapping com `errors.As`

Parte da seção Lógica & Fluxo do Journey de GO da Coddy — lição 41 de 68.

Enquanto o errors.Is ajuda você a identificar valores de erro específicos em uma cadeia, às vezes você precisa acessar os campos e dados reais de um tipo de erro personalizado. A função errors.As fornece essa capacidade ao encontrar o primeiro erro em uma cadeia que corresponde a um tipo específico e extraí-lo para inspeção.

A função errors.As recebe dois parâmetros: o erro a ser examinado e um ponteiro para uma variável do tipo de erro de destino. Se ela encontrar um tipo de erro correspondente na cadeia, ela define sua variável para esse erro e retorna true:

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

Isso é particularmente poderoso ao trabalhar com tipos de erro personalizados que contêm contexto adicional. Ao contrário de errors.Is, que apenas verifica a igualdade, errors.As extrai a instância real do erro, permitindo que você acesse seus campos e métodos. Isso torna o tratamento de erros mais sofisticado e informativo em aplicações complexas.

quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

challenge icon

Desafio

Fácil

Construa um sistema de tratamento de erros de API que utilize errors.As para extrair e examinar tipos de erro personalizados de cadeias de erros envolvidos (wrapped). Este desafio demonstra como usar errors.As para acessar os campos e dados de tipos de erro personalizados específicos, mesmo quando eles foram envolvidos com contexto adicional.

Você receberá duas entradas:

  • Uma string contendo detalhes da requisição da API no formato "endpoint,method,error_code,error_field" (ex: "/users,POST,400,email")
  • Uma string contendo o contexto do sistema no formato "service_name,request_id" (ex: "UserAPI,req_12345")

Sua tarefa é:

  1. Criar um tipo de erro personalizado chamado struct APIError com três campos:
    • Code (int) - o código de status HTTP
    • Field (string) - o campo que causou o erro
    • Message (string) - uma descrição do erro
  2. Implementar o método Error() string para APIError que retorna: "API error [code]: [message] (field: [field])"
  3. Analisar a primeira entrada dividindo-a por vírgulas para obter endpoint, method, error code e error field
  4. Analisar a segunda entrada dividindo-a por vírgulas para obter service name e request ID
  5. Converter a string do código de erro em um inteiro
  6. Criar uma instância de APIError baseada no código de erro:
    • Se o código for 400: mensagem "invalid request data"
    • Se o código for 401: mensagem "authentication required"
    • Se o código for 404: mensagem "resource not found"
    • Se o código for 500: mensagem "internal server error"
    • Para qualquer outro código: mensagem "unknown error"
  7. Criar um erro envolvido de nível de endpoint usando fmt.Errorf com %w: "[method] [endpoint] failed: %w"
  8. Criar um erro envolvido de nível de serviço: "[service_name] request [request_id] failed: %w"
  9. Usar errors.As para extrair o APIError da cadeia de erros envolvidos e exibir o resultado da extração:
    • Se a extração for bem-sucedida: "API error extracted successfully"
    • Se a extração falhar: "Failed to extract API error"
  10. Se a extração for bem-sucedida, exibir os detalhes do erro extraído:
    • "Extracted Error Details:"
    • "Code: [code]"
    • "Field: [field]"
    • "Message: [message]"
    • "Full error: [full_error_message_from_Error_method]"
  11. Exibir a cadeia de erros completa:
    • "Error Chain:"
    • "Original: [original_api_error_message]"
    • "Endpoint level: [endpoint_level_error_message]"
    • "Service level: [service_level_error_message]"
  12. Exibir uma análise final:
    • "Error Analysis:"
    • "Service: [service_name]"
    • "Request ID: [request_id]"
    • "Endpoint: [method] [endpoint]"
    • "HTTP Status: [code]"
    • "Problem Field: [field]"
    • "Error Category: [error_category]" onde error_category é "Client Error" para códigos 400-499, "Server Error" para códigos 500-599, ou "Unknown" para outros códigos

Use o pacote strings para dividir as strings de entrada por vírgulas, o pacote strconv para converter a string do código de erro em um inteiro, o pacote errors para errors.As, e o pacote fmt para o envolvimento de erros. Este desafio demonstra como o errors.As permite que você acesse os campos e métodos específicos de tipos de erro personalizados dentro de cadeias de erros envolvidos, permitindo um tratamento e análise de erros sofisticados.

Folha de consulta

A função errors.As extrai tipos de erro específicos de cadeias de erros, permitindo o acesso a campos e métodos de erro personalizados.

errors.As recebe dois parâmetros: o erro a ser examinado e um ponteiro para uma variável do tipo de erro de destino:

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

Ao contrário de errors.Is, que apenas verifica a igualdade, o errors.As extrai a instância real do erro, permitindo o acesso aos seus campos e métodos para um tratamento de erros mais sofisticado.

Experimente você mesmo

package main

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

func main() {
	// Ler entrada
	var apiDetails string
	var systemContext string
	fmt.Scanln(&apiDetails)
	fmt.Scanln(&systemContext)
	
	// Analisar 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]
	
	// Converter código de erro para inteiro
	errorCode, _ := strconv.Atoi(errorCodeStr)
	
	// TODO: Escreva seu código abaixo
	// 1. Criar a struct APIError com os campos Code, Field, Message
	// 2. Implementar o método Error() para APIError
	// 3. Criar uma instância de APIError baseada no código de erro
	// 4. Criar erros encapsulados (nível de endpoint e nível de serviço)
	// 5. Usar errors.As para extrair APIError da cadeia de erros encapsulados
	// 6. Exibir o resultado da extração e os detalhes do erro
	// 7. Exibir a cadeia de erros e a análise final
	
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Lógica & Fluxo