Médio Go

Erro customizado com código de status

Enunciado

Crie um tipo HTTPError que implementa error e contém os campos Status int e Message string. A função requisitar(url string) error retorna um *HTTPError com status 404 se a URL for "/nao-existe". No main, use errors.As para extrair o *HTTPError e imprimir o status e a mensagem.

Requisitos

  • Definir a struct HTTPError com campos Status e Message.
  • Implementar o método Error() string para *HTTPError.
  • A função requisitar retorna *HTTPError com status 404 para a URL específica.
  • No main, usar errors.As para obter o erro customizado e imprimir Status e Message.

Código inicial

package main

import (
	"errors"
	"fmt"
)

// Defina HTTPError

func requisitar(url string) error {
	// Implemente
	return nil
}

func main() {
	// Chame requisitar("/nao-existe") e trate o erro
}

Saída esperada

Status: 404, Mensagem: não encontrado
Ver dica

O método Error() deve retornar uma string formatada. Use errors.As para converter o erro para *HTTPError.

Mostrar solução
package main

import (
	"errors"
	"fmt"
)

type HTTPError struct {
	Status  int
	Message string
}

func (e *HTTPError) Error() string {
	return fmt.Sprintf("HTTP %d: %s", e.Status, e.Message)
}

func requisitar(url string) error {
	if url == "/nao-existe" {
		return &HTTPError{Status: 404, Message: "não encontrado"}
	}
	return nil
}

func main() {
	err := requisitar("/nao-existe")
	var httpErr *HTTPError
	if errors.As(err, &httpErr) {
		fmt.Printf("Status: %d, Mensagem: %s\n", httpErr.Status, httpErr.Message)
	}
}

Passo a passo

  1. Definimos a struct HTTPError com os campos Status e Message.
  2. Implementamos o método Error() string no ponteiro *HTTPError, formatando a mensagem.
  3. A função requisitar verifica a URL e retorna um *HTTPError com status 404 para /nao-existe.
  4. No main, chamamos requisitar e armazenamos o erro.
  5. Declaramos uma variável httpErr do tipo *HTTPError e usamos errors.As para tentar converter o erro para esse tipo.
  6. Se a conversão for bem-sucedida, imprimimos os campos.

Por que funciona

Erros customizados permitem carregar dados estruturados. errors.As percorre a cadeia de erros (incluindo erros envolvidos) e verifica se algum deles é do tipo alvo, preenchendo a variável com o valor encontrado.

Erros comuns

  • Implementar Error() no valor e não no ponteiro: se Error() for definido em HTTPError (valor), então *HTTPError também implementa error, mas errors.As com *HTTPError pode não funcionar como esperado. Prefira definir no ponteiro.
  • Usar errors.Is em vez de errors.As: errors.Is compara valores, não tipos. Para extrair dados, use errors.As.
  • Esquecer de passar o endereço para errors.As: o segundo argumento deve ser um ponteiro para a variável que receberá o erro.

Outra forma de resolver

Poderia usar uma asserção de tipo direta: if e, ok := err.(*HTTPError); ok { ... }. Mas isso não funciona se o erro estiver envolvido com %w. errors.As é mais robusto.

Saída esperada

Status: 404, Mensagem: não encontrado