Wrapping de Erros com `%w`
Parte da seção Lógica & Fluxo do Journey de GO da Coddy — lição 39 de 68.
Quando ocorrem erros em sua aplicação, eles frequentemente precisam de contexto adicional à medida que sobem pelas diferentes camadas do seu código. O Go fornece um mecanismo poderoso para isso por meio do embrulho de erro (error wrapping) usando o verbo de formatação %w com fmt.Errorf.
O empacotamento de erros (error wrapping) permite adicionar informações contextuais a um erro existente enquanto preserva o erro original subjacente. Isso cria uma cadeia de erros que mantém o histórico completo do que deu errado:
originalErr := errors.New("file not found")
wrappedErr := fmt.Errorf("failed to load config: %w", originalErr)O verbo %w é especial - ele diz ao fmt.Errorf para envolver o erro em vez de apenas convertê-lo em uma string. Isso preserva o erro original para que ele possa ser examinado mais tarde usando funções como errors.Is e errors.As.
Este padrão é particularmente valioso em aplicações maiores, onde um erro pode passar por múltiplas funções, cada uma adicionando seu próprio contexto. Por exemplo, um erro de conexão com o banco de dados pode ser envolvido com "failed to connect to database", depois envolvido novamente com "unable to start server", criando um rastro claro do que aconteceu e onde.
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 processamento de arquivos que envolve erros com informações contextuais à medida que eles se propagam por diferentes camadas da sua aplicação. Este desafio demonstra como usar o verbo de formatação %w com fmt.Errorf para criar cadeias de erros que preservam o erro original enquanto adicionam um contexto significativo.
Você receberá duas entradas:
- Uma string contendo detalhes da operação de arquivo no formato
"filename,operation,status"(ex:"config.json,read,permission_denied") - Uma string contendo o contexto do sistema no formato
"service_name,component"(ex:"UserService,ConfigLoader")
Sua tarefa é:
- Analisar a primeira entrada dividindo-a por vírgulas para obter o filename, operation e status
- Analisar a segunda entrada dividindo-a por vírgulas para obter o service name e component
- Criar um erro original baseado no status usando
errors.New():- Se o status for
"permission_denied":"permission denied" - Se o status for
"not_found":"file not found" - Se o status for
"corrupted":"file corrupted" - Para qualquer outro status:
"unknown error"
- Se o status for
- Criar um erro envolvido (wrapped) em nível de arquivo usando
fmt.Errorfcom%w:"failed to [operation] file [filename]: %w" - Criar um erro envolvido em nível de componente:
"[component] error: %w" - Criar um erro envolvido em nível de serviço:
"[service_name] operation failed: %w" - Exibir a cadeia de erros imprimindo cada nível:
"Original error: [original_error_message]""File level: [file_level_error_message]""Component level: [component_level_error_message]""Service level: [service_level_error_message]"
- Exibir um resumo da cadeia de erros:
"Error Chain Summary:""File: [filename]""Operation: [operation]""Component: [component]""Service: [service_name]""Root cause: [original_error_message]"
Use o pacote strings para dividir as strings de entrada por vírgulas, o pacote errors para criar o erro original e o pacote fmt para criar os erros envolvidos. Este desafio demonstra como o encapsulamento de erros com %w cria uma trilha clara de contexto à medida que os erros passam por diferentes camadas da sua aplicação, tornando a depuração muito mais eficaz.
Folha de consulta
O encapsulamento de erros (error wrapping) permite adicionar informações contextuais a um erro existente enquanto preserva o erro original. Use o verbo de formatação %w com fmt.Errorf:
originalErr := errors.New("file not found")
wrappedErr := fmt.Errorf("failed to load config: %w", originalErr)O verbo %w preserva o erro original para que ele possa ser examinado posteriormente usando funções como errors.Is e errors.As. Isso cria uma cadeia de erros que mantém o histórico completo do que deu errado, o que é valioso quando os erros passam por múltiplas funções em aplicações maiores.
Experimente você mesmo
package main
import (
"errors"
"fmt"
"strings"
)
func main() {
// Ler entrada
var fileDetails string
var systemContext string
fmt.Scanln(&fileDetails)
fmt.Scanln(&systemContext)
// Analisar entradas
fileInfo := strings.Split(fileDetails, ",")
filename := fileInfo[0]
operation := fileInfo[1]
status := fileInfo[2]
contextInfo := strings.Split(systemContext, ",")
serviceName := contextInfo[0]
component := contextInfo[1]
// TODO: Escreva seu código abaixo
// Criar erro original baseado no status
// Criar erro encapsulado no nível de arquivo
// Criar erro encapsulado no nível de componente
// Criar erro encapsulado no nível de serviço
// Imprimir cada nível de erro e o resumo
}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