Desafio Go
Erros personalizados com errors.As
Enunciado
Implemente um tipo de erro personalizado ErroValidacao com campos Campo e Mensagem. Crie uma função ValidarUsuario(nome string, idade int) error que retorna um *ErroValidacao se nome estiver vazio ou idade for menor que 18. A função deve retornar o primeiro erro encontrado. No main, chame ValidarUsuario("", 20) e use errors.As para extrair o *ErroValidacao e imprimir "Erro no campo: nome - mensagem: nome não pode ser vazio". Depois, chame ValidarUsuario("João", 15) e faça o mesmo para o campo idade.
Requisitos
- Definir a struct
ErroValidacaocom camposCampoeMensageme métodoError() string. - A função
ValidarUsuarioretorna*ErroValidacaopara nome vazio ou idade < 18. - No
main, usarerrors.Aspara extrair o erro e imprimir a mensagem formatada. - Imprimir exatamente
"Erro no campo: nome - mensagem: nome não pode ser vazio"e"Erro no campo: idade - mensagem: idade mínima é 18".
Código inicial
package main
import (
"errors"
"fmt"
)
type ErroValidacao struct {
Campo string
Mensagem string
}
func (e *ErroValidacao) Error() string {
return fmt.Sprintf("erro no campo %s: %s", e.Campo, e.Mensagem)
}
func ValidarUsuario(nome string, idade int) error {
// Implemente
return nil
}
func main() {
// Chame ValidarUsuario e use errors.As
}
Saída esperada
Erro no campo: nome - mensagem: nome não pode ser vazio
Erro no campo: idade - mensagem: idade mínima é 18
Ver dica
Use var valErr *ErroValidacao e errors.As(err, &valErr). Depois acesse valErr.Campo e valErr.Mensagem.
Mostrar solução
package main
import (
"errors"
"fmt"
)
// ErroValidacao representa um erro de validação com campo e mensagem.
type ErroValidacao struct {
Campo string
Mensagem string
}
// Error implementa a interface error.
func (e *ErroValidacao) Error() string {
return fmt.Sprintf("erro no campo %s: %s", e.Campo, e.Mensagem)
}
// ValidarUsuario retorna um *ErroValidacao se nome for vazio ou idade < 18.
func ValidarUsuario(nome string, idade int) error {
if nome == "" {
return &ErroValidacao{Campo: "nome", Mensagem: "nome não pode ser vazio"}
}
if idade < 18 {
return &ErroValidacao{Campo: "idade", Mensagem: "idade mínima é 18"}
}
return nil
}
func main() {
// Teste 1: nome vazio
err := ValidarUsuario("", 20)
if err != nil {
var valErr *ErroValidacao
if errors.As(err, &valErr) {
fmt.Printf("Erro no campo: %s - mensagem: %s\n", valErr.Campo, valErr.Mensagem)
}
}
// Teste 2: idade inválida
err = ValidarUsuario("João", 15)
if err != nil {
var valErr *ErroValidacao
if errors.As(err, &valErr) {
fmt.Printf("Erro no campo: %s - mensagem: %s\n", valErr.Campo, valErr.Mensagem)
}
}
}
Passo a passo
- Definimos a struct
ErroValidacaocom os camposCampoeMensagem. - Implementamos o método
Error() stringpara que*ErroValidacaosatisfaça a interfaceerror. - A função
ValidarUsuarioverifica primeiro senomeé vazio; se for, retorna um*ErroValidacaocom os detalhes. - Se
idade < 18, retorna outro*ErroValidacaocom os detalhes da idade. - No
main, para cada chamada, usamoserrors.Ascom uma variável do tipo*ErroValidacaopara extrair o erro concreto da cadeia. - Se a extração for bem-sucedida, acessamos os campos e imprimimos a mensagem formatada.
Por que funciona
errors.As percorre a cadeia de erros verificando se algum erro é do tipo alvo (no caso, *ErroValidacao). Se encontrar, atribui o valor à variável fornecida e retorna true. Isso permite acessar campos específicos do erro personalizado, mesmo que ele esteja envolto por outros erros.
Erros comuns
- Passar
&valErrcomo*ErroValidacaoem vez de**ErroValidacao:errors.Asespera um ponteiro para a variável que receberá o erro. O correto évar valErr *ErroValidacao; errors.As(err, &valErr). - Retornar
ErroValidacao(valor) em vez de*ErroValidacao: se o métodoError()tem receptor ponteiro, apenas*ErroValidacaoimplementaerror. Retornar valor causaria erro de compilação. - Esquecer de verificar o retorno de
errors.As: se o tipo não corresponder, a variável permanecenile um panic pode ocorrer ao acessar campos.
Outra forma de resolver
Se você precisa apenas da mensagem, pode usar err.Error(). Mas para acessar campos específicos, errors.As é a ferramenta correta.
Saída esperada
Erro no campo: nome - mensagem: nome não pode ser vazio
Erro no campo: idade - mensagem: idade mínima é 18