Validação com go-playground/validator
encoding/json mapeia bytes para tipos Go; ele não impõe regras de negócios.
Busque em todas as páginas da documentação
encoding/json mapeia bytes para tipos Go; ele não impõe regras de negócios.
github.com/go-playground/validator/v10 (verifique a versão na compilação) lê as tags de struct validate e retorna erros em nível de campo adequados para respostas HTTP 400.
Decodifique o JSON primeiro, depois chame validator.Struct na struct populada.
As tags expressam restrições comuns (required, email, gte, oneof) e validadores personalizados estendem o motor para regras específicas do domínio.
A validação permanece separada da serialização para que a mesma struct possa ser usada em ambos os sentidos para JSON sem incorporar políticas no formato de transmissão.
Cartão de receita de referência rápida - pronto para copiar e colar.
import "github.com/go-playground/validator/v10"
var validate = validator.New()
type CreateOrder struct {
SKU string `json:"sku" validate:"required,alphanum,min=3,max=32"`
Qty int `json:"qty" validate:"required,gte=1,lte=1000"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { /* 400 */ }
if err := validate.Struct(req); err != nil {
verrs := err.(validator.ValidationErrors)
// mapear para detalhes do problema JSON
}Quando usar isso:
json para revisabilidade.package main
import (
"encoding/json"
"fmt"
"strings"
"github.com/go-playground/validator/v10"
)
type Signup struct {
Email string `json:"email" validate:"required,email"`
Age int `json:"age" validate:"gte=13,lte=120"`
Country string `json:"country" validate:"required,len=2,alpha"`
Referral string `json:"referral" validate:"omitempty,alphanum"`
}
func formatErrors(err error) string {
var b strings.Builder
for _, fe := range err.(validator.ValidationErrors) {
fmt.Fprintf(&b, "%s falhou em %s; ", fe.Field(), fe.Tag())
}
return strings.TrimSuffix(b.String(), "; ")
}
func main() {
validate := validator.New()
raw := []byte(`{"email":"not-an-email","age":10,"country":"USA"}`)
var s Signup
_ = json.Unmarshal(raw, &s)
if err := validate.Struct(s); err != nil {
fmt.Println(formatErrors(err))
}
good := Signup{Email: "ada@example.com", Age: 30, Country: "US"}
fmt.Println(validate.Struct(good))
}O que isso demonstra:
validator.ValidationErrors expõe metadados de campo, tag e parâmetro.omitempty ignora regras quando o campo é zero.| Tag | Significado | Exemplo |
|---|---|---|
required | Valor não zero | IDs, emails |
omitempty | Ignorar outras regras se zero | Referência opcional |
email | Formato de e-mail | Cadastro de usuário |
gte / lte | Limites numéricos | Quantidades |
len | Comprimento de string/array | Códigos de país |
oneof | Strings de enumeração | oneof=red green blue |
dive | Validar elementos de slice | validate:"dive,email" |
A lista completa de tags está na documentação upstream (verifique a versão na compilação).
validate := validator.New()
_ = validate.RegisterValidation("sku", func(fl validator.FieldLevel) bool {
s := fl.Field().String()
return strings.HasPrefix(s, "SKU-")
})Use tags personalizadas para regras de domínio que são estranhas como regex.
Mantenha os validadores puros e rápidos; eles rodam por requisição.
http.MaxBytesReader.json.Decoder com DisallowUnknownFields opcional.validate.Struct.gin oferece tags binding que envolvem o validador; echo tem vinculadores semelhantes.
Você ainda pode usar o validador diretamente para código não framework.
validator.ValidationErrors pode alimentar en_translations ou tradutores personalizados para mensagens de usuário final.
Registre detalhes técnicos no lado do servidor; retorne mensagens seguras no lado do cliente.
// validate:"-" ignora um campo inteiramente (timestamps definidos pelo servidor)
// Use ponteiros para que required possa distinguir ausente vs zero para númerosCombine com Tags de Struct para JSON, DB e Validação para alinhamento de tags.
Struct seja executado. Correção: valide explicitamente nos manipuladores.required em zero de int - 0 falha em required para inteiros. Correção: use ponteiros para números opcionais ou remova required quando 0 for válido.email não é perfeito - A tag verifica o formato, não a entregabilidade. Correção: adicione fluxos de confirmação para contas reais.Struct na raiz; structs internas precisam de tags validate em campos aninhados. Correção: use dive para slices de DTOs aninhados.validator.New por requisição - Criar o motor a cada requisição é lento. Correção: reutilize uma instância validate em nível de pacote; registre validadores personalizados em init.| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| go-playground/validator | APIs HTTP baseadas em tags | Regras de gráfico complexas |
| Verificações escritas à mão | Manipuladores minúsculos | Formulários grandes |
| OpenAPI / JSON Schema | CI baseado em contrato | Validação apenas em tempo de execução |
| CEL ou motores de política | Regras de autorização | Formatos de campo simples |
| Restrições Protobuf | gRPC com protovalidate | Apenas REST simples |
Depois - o unmarshalling deve popular a struct primeiro.
Sim - vincule a query a uma struct e chame Struct.
Vinculadores de framework frequentemente compartilham o mesmo motor de tag.
Use structs parciais separadas ou ponteiros para que required não seja acionado em campos ausentes.
Use validação em nível de struct com RegisterStructValidation.
Mantenha a lógica entre campos legível e testada.
Uma instância Validate configurada é segura para chamadas Struct concorrentes.
Registre validadores personalizados antes de servir tráfego.
Valide na borda; mantenha restrições de DB como último recurso.
Regras duplicadas são aceitáveis para defesa em profundidade.
Sim - qualquer struct populada se qualifica.
As tags são agnósticas ao transporte.
400 com erros de campo legíveis por máquina para APIs públicas.
Registre detalhes completos no lado do servidor.
Ele não executa o validador.
Use testes unitários por DTO e linters opcionais para alinhamento de nomenclatura de tags.
Teste em tabela com fixtures JSON válidas e inválidas por endpoint.
Afirme as tags de erro, não apenas a presença de erro.
Versões de Stack: Esta página foi escrita para Go 1.26.x (GC padrão Green Tea, go fix modernizers - verifique o patch na compilação), chi (última versão - verifique na compilação), gin (última versão - verifique na compilação), echo (última versão - verifique na compilação), google.golang.org/grpc (última versão - verifique na compilação), sigs.k8s.io/controller-runtime (última versão - verifique na compilação), kubebuilder (última versão - verifique na compilação), tinygo (última versão - verifique os alvos de placa na compilação), wazero (última versão - verifique na compilação) e golangci-lint (última versão - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 18 de jul. de 2026