Menu
Coddy logo textTech

Unwrapping com `errors.Is`

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

Ao trabalhar com erros encapsulados, você precisa de uma maneira de verificar se um erro específico existe em qualquer lugar na cadeia de erros. A função errors.Is fornece exatamente essa capacidade, permitindo identificar erros sentinela mesmo quando eles foram encapsulados várias vezes.

A função errors.Is recebe dois parâmetros: o erro que você deseja examinar e o erro alvo que você está procurando. Ela retorna true se o erro alvo for encontrado em qualquer lugar na cadeia de erros:

var ErrNotFound = errors.New("not found")

wrappedErr := fmt.Errorf("failed to load user: %w", ErrNotFound)

if errors.Is(wrappedErr, ErrNotFound) {
    fmt.Println("This is a not found error")
}

Esta é a maneira moderna e recomendada de verificar erros específicos em Go. Ao contrário da comparação de strings ou verificações de igualdade direta, errors.Is funciona corretamente com erros encapsulados e segue a cadeia de erros para encontrar correspondências. Isso torna o seu tratamento de erros robusto e confiável, mesmo quando os erros passam por várias camadas da sua aplicação.

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 monitoramento de conexão de banco de dados que utiliza errors.Is para identificar erros de conexão específicos em cadeias de erros envolvidos (wrapped). Este desafio demonstra como usar errors.Is para detectar erros sentinela mesmo quando eles foram envolvidos com contexto adicional através de múltiplas camadas da aplicação.

Você receberá duas entradas:

  • Uma string contendo detalhes da operação do banco de dados no formato "database_name,operation,error_type" (ex: "users_db,connect,connection_timeout")
  • Uma string contendo o contexto da aplicação no formato "service_name,retry_count" (ex: "AuthService,3")

Sua tarefa é:

  1. Definir três erros sentinela usando errors.New():
    • ErrConnectionTimeout com a mensagem "connection timeout"
    • ErrConnectionRefused com a mensagem "connection refused"
    • ErrDatabaseNotFound com a mensagem "database not found"
  2. Analisar a primeira entrada dividindo-a por vírgulas para obter o nome do banco de dados, a operação e o tipo de erro
  3. Analisar a segunda entrada dividindo-a por vírgulas para obter o nome do serviço e a contagem de tentativas
  4. Criar o erro original baseado no tipo de erro:
    • Se o tipo de erro for "connection_timeout": use ErrConnectionTimeout
    • Se o tipo de erro for "connection_refused": use ErrConnectionRefused
    • Se o tipo de erro for "database_not_found": use ErrDatabaseNotFound
    • Para qualquer outro tipo de erro: use errors.New("unknown database error")
  5. Criar um erro envolvido em nível de banco de dados usando fmt.Errorf com %w: "failed to [operation] database [database_name]: %w"
  6. Criar um erro envolvido em nível de serviço: "[service_name] database operation failed after [retry_count] retries: %w"
  7. Usar errors.Is para verificar se o erro envolvido final corresponde a cada erro sentinela e exibir os resultados:
    • "Checking for connection timeout: [true/false]"
    • "Checking for connection refused: [true/false]"
    • "Checking for database not found: [true/false]"
  8. Exibir a cadeia de erros:
    • "Error Chain:"
    • "Original: [original_error_message]"
    • "Database level: [database_level_error_message]"
    • "Service level: [service_level_error_message]"
  9. Exibir a análise do erro:
    • "Error Analysis:"
    • "Database: [database_name]"
    • "Operation: [operation]"
    • "Service: [service_name]"
    • "Retries: [retry_count]"
    • "Error type detected: [detected_error_type]" onde detected_error_type é um dos seguintes: "Connection Timeout", "Connection Refused", "Database Not Found", ou "Unknown Error"

Use o pacote strings para dividir as strings de entrada por vírgulas, o pacote errors para os erros sentinela e errors.Is, e o pacote fmt para o envolvimento de erros. Este desafio demonstra como o errors.Is fornece uma identificação de erro robusta que funciona corretamente com erros envolvidos, tornando-o essencial para o tratamento confiável de erros em aplicações complexas.

Folha de consulta

A função errors.Is verifica se um erro específico existe em qualquer lugar de uma cadeia de erros, mesmo quando encapsulado (wrapped) várias vezes:

var ErrNotFound = errors.New("not found")

wrappedErr := fmt.Errorf("failed to load user: %w", ErrNotFound)

if errors.Is(wrappedErr, ErrNotFound) {
    fmt.Println("This is a not found error")
}

errors.Is recebe dois parâmetros: o erro a ser examinado e o erro alvo a ser encontrado. Ela retorna true se o erro alvo for encontrado em qualquer lugar da cadeia de erros.

Esta é a maneira moderna e recomendada de verificar erros específicos em Go, pois funciona corretamente com erros encapsulados, ao contrário da comparação de strings ou verificações de igualdade direta.

Experimente você mesmo

package main

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

func main() {
	// Lê a entrada
	var dbOperation string
	var appContext string
	fmt.Scanln(&dbOperation)
	fmt.Scanln(&appContext)
	
	// Faz o parsing das entradas
	dbParts := strings.Split(dbOperation, ",")
	databaseName := dbParts[0]
	operation := dbParts[1]
	errorType := dbParts[2]
	
	contextParts := strings.Split(appContext, ",")
	serviceName := contextParts[0]
	retryCount := contextParts[1]
	
	// TODO: Escreva seu código abaixo
	// 1. Defina os três erros sentinela usando errors.New()
	// 2. Crie o erro original baseado no tipo de erro
	// 3. Crie o erro encapsulado (wrapped) de nível de banco de dados usando fmt.Errorf com %w
	// 4. Crie o erro encapsulado de nível de serviço
	// 5. Use errors.Is para verificar cada erro sentinela
	// 6. Exiba os resultados e a cadeia de erros
	
}
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