Desafio Go
Agregando erros com errors.Join
Enunciado
Crie uma função validarUsuario(nome, email string) error que valida nome e email. Se ambos forem inválidos, retorne um erro combinado usando errors.Join. Defina erros sentinela ErrNomeVazio e ErrEmailInvalido. No main, chame a função com dados inválidos, verifique com errors.Is se ambos os erros estão presentes e imprima a mensagem combinada.
Requisitos
- Definir os erros sentinela
ErrNomeVazioeErrEmailInvalido. - A função
validarUsuarioretornaerrors.Joindos erros encontrados. - No
main, usarerrors.Ispara verificar cada erro individualmente. - Imprimir a mensagem do erro combinado.
Código inicial
package main
import (
"errors"
"fmt"
)
// Defina erros sentinela
func validarUsuario(nome, email string) error {
// Implemente
return nil
}
func main() {
// Chame validarUsuario("", "invalido") e trate os erros
}
Saída esperada
Erro de nome: nome não pode ser vazio
Erro de email: email inválido
Erro combinado: nome não pode ser vazio
email inválido
Ver dica
Use errors.Join para combinar os erros. No main, verifique cada sentinela com errors.Is e imprima a mensagem do erro combinado.
Mostrar solução
package main
import (
"errors"
"fmt"
)
var (
ErrNomeVazio = errors.New("nome não pode ser vazio")
ErrEmailInvalido = errors.New("email inválido")
)
func validarUsuario(nome, email string) error {
var errs []error
if nome == "" {
errs = append(errs, ErrNomeVazio)
}
if email == "invalido" {
errs = append(errs, ErrEmailInvalido)
}
return errors.Join(errs...)
}
func main() {
err := validarUsuario("", "invalido")
if errors.Is(err, ErrNomeVazio) {
fmt.Println("Erro de nome:", ErrNomeVazio)
}
if errors.Is(err, ErrEmailInvalido) {
fmt.Println("Erro de email:", ErrEmailInvalido)
}
fmt.Println("Erro combinado:", err)
}
Passo a passo
- Declaramos dois erros sentinela com
errors.New. - Na função
validarUsuario, criamos um sliceerrspara acumular os erros. - Se
nomefor vazio, adicionamosErrNomeVazioao slice. - Se
emailfor"invalido", adicionamosErrEmailInvalido. - Retornamos
errors.Join(errs...), que combina todos os erros em um único erro. - No
main, chamamos a função com dados inválidos. - Usamos
errors.Ispara verificar cada erro sentinela individualmente.errors.Ispercorre a árvore de erros combinados. - Imprimimos a mensagem do erro combinado, que contém as mensagens separadas por nova linha.
Por que funciona
errors.Join cria um erro que contém múltiplos erros. Ele implementa Unwrap() []error, permitindo que errors.Is e errors.As percorram todos os erros combinados. Isso é útil quando várias validações falham e você quer reportar todas de uma vez.
Erros comuns
- Passar um slice vazio para
errors.Join: retornanil, o que pode ser confundido com sucesso. Verifique se há erros antes de chamar. - Usar
errors.Iscom o erro combinado e esperar que ele seja igual a um dos erros:errors.Isverifica se algum erro na cadeia é igual ao alvo, então funciona. - Esquecer de importar
errors: erro de compilação. - Tentar usar
==para comparar o erro combinado com um sentinela: não funciona, pois são valores diferentes. Useerrors.Is.
Outra forma de resolver
Poderia retornar uma struct customizada que contém um slice de erros e implementa Error() e Unwrap() []error. Mas errors.Join já faz isso de forma padrão e é mais simples.
Saída esperada
Erro de nome: nome não pode ser vazio
Erro de email: email inválido
Erro combinado: nome não pode ser vazio
email inválido