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.
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Desafio
FácilConstrua 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 é:
- Criar um tipo de erro personalizado chamado struct
APIErrorcom três campos:Code(int) - o código de status HTTPField(string) - o campo que causou o erroMessage(string) - uma descrição do erro
- Implementar o método
Error() stringparaAPIErrorque retorna:"API error [code]: [message] (field: [field])" - Analisar a primeira entrada dividindo-a por vírgulas para obter endpoint, method, error code e error field
- Analisar a segunda entrada dividindo-a por vírgulas para obter service name e request ID
- Converter a string do código de erro em um inteiro
- Criar uma instância de
APIErrorbaseada 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"
- Se o código for 400: mensagem
- Criar um erro envolvido de nível de endpoint usando
fmt.Errorfcom%w:"[method] [endpoint] failed: %w" - Criar um erro envolvido de nível de serviço:
"[service_name] request [request_id] failed: %w" - Usar
errors.Aspara extrair oAPIErrorda 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"
- Se a extração for bem-sucedida:
- 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]"
- 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]"
- 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
}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
1Fluxo de Controle Avançado
Switch com `fallthrough`Interrompendo Loops AninhadosContinuando um Loop EspecíficoA Instrução `goto`Recapitulação - Controle de Loop Avançado4Projeto: Lista de Tarefas Simples
Configuração do ProjetoAdicionando uma Tarefa7Tratamento de Erros em Profundidade
Tipos de Erro PersonalizadosWrapping de Erros com `%w`Unwrapping com `errors.Is`Unwrapping com `errors.As`Entendendo o `panic`Usando o `recover`Recapitulação - Divisão Segura2Structs e Métodos
Definindo Métodos em StructsRecebedores de ValorRecebedores de PonteiroEscolhendo RecebedoresMétodos vs FunçõesRecapitulação - Comportamento de Structs5Mapas em Profundidade
Mapas de StructsPonteiros como Valores de MapVerificando Mapas NilComparando MapasRecapitulação - Contador de Frequência de Palavras3Interfaces (O Básico)
O que é uma Interface?Definindo uma InterfaceImplementando uma InterfaceUsando Tipos de InterfaceInterface VaziaAsserções de TipoType SwitchRecapitulação - Formas e Comportamentos