Validação, migrate & sqlc
Três bibliotecas focadas cobrem bordas comuns da camada de dados em serviços Go: go-playground/validator para tags de struct, golang-migrate para versões de schema e sqlc para geração de código SQL type-safe.
Busque em todas as páginas da documentação
Três bibliotecas focadas cobrem bordas comuns da camada de dados em serviços Go: go-playground/validator para tags de struct, golang-migrate para versões de schema e sqlc para geração de código SQL type-safe.
Elas complementam database/sql sem impor um ORM completo.
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 CreateUser struct {
Email string `json:"email" validate:"required,email"`
Age int `json:"age" validate:"gte=18,lte=120"`
}
func check(in CreateUser) error {
return validate.Struct(in)
}migrate -path ./migrations -database "${DATABASE_URL}" up
sqlc generateQuando usar isso:
QueryRow baseadas em stringspackage api
import (
"context"
"encoding/json"
"net/http"
"github.com/go-playground/validator/v10"
)
var validate = validator.New()
type createUserRequest struct {
Email string `json:"email" validate:"required,email"`
Name string `json:"name" validate:"required,min=1,max=128"`
}
func createUser(w http.ResponseWriter, r *http.Request) {
var in createUserRequest
if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
http.Error(w, "invalid json", http.StatusBadRequest)
return
}
if err := validate.Struct(in); err != nil {
http.Error(w, formatValidation(err), http.StatusBadRequest)
return
}
// chama o serviço com DTO validado
w.WriteHeader(http.StatusCreated)
}
func formatValidation(err error) string {
// mapeia validator.ValidationErrors para JSON com escopo de campo em produção
return err.Error()
}-- migrations/000001_create_users.up.sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
name TEXT NOT NULL
);# sqlc.yaml
version: "2"
sql:
- engine: "postgresql"
queries: "queries/"
schema: "migrations/"
gen:
go:
package: "db"
out: "internal/db"O que isso demonstra:
validator.Validate.up/down SQL em ordem.sqlc generate quando as consultas ou o schema mudarem.| Tag | Significado |
|---|---|
required | Valor não zero |
email | Formato de e-mail RFC-ish |
uuid | String UUID |
gte=0 / lte=100 | Limites numéricos |
oneof=red green | Strings de enumeração |
| Prática | Por quê |
|---|---|
| Uma alteração por arquivo de migração | Rollback e revisão mais fáceis |
| Expandir-contrair para zero downtime | Adicionar coluna nullable antes do backfill |
| Executar em CI contra banco de dados efêmero | Capturar sintaxe SQL precocemente |
| Nunca de manipuladores de requisição | Evitar corrida com trabalhos de deploy |
queries/users.sql com anotações -- name: GetUser :one.internal/db gerado ou regenere em CI.// O binding do Gin/Echo pode envolver o validator - ainda mantenha os DTOs na borda
// database/sql continua sendo o driver de runtime; sqlc não substitui o ajuste do pool pgxvalidator.ValidationErrors para problem+json para clientes de API.sqlc.yaml.validator.New() por pacote ou helper de teste com cuidado t.Parallel.down puladas em produção - equipes executam apenas up; down quebrado esconde até emergência. Correção: teste down 1 em CI em bancos de dados descartáveis.| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Validação manual | Poucos campos, sem tags | DTOs grandes gerados por OpenAPI |
| Migrações goose | Equipe prefere arquivos de migração Go | Você já padronizou a CLI migrate |
| ORM GORM / ent | Protótipos CRUD rápidos | Você precisa de SQL ajustado e consultas explícitas |
| pgx sem sqlc | Contagem de consultas minúscula | Dezenas de consultas divergem do schema |
Conecte os validadores do framework à mesma instância validator.Validate; mantenha os structs DTO compartilhados entre os frameworks.
Ambos funcionam; escolha um por organização e documente a CLI nos runbooks de deploy - a seção de bancos de dados os compara em profundidade.
Ele substitui consultas baseadas em strings e parte do boilerplate de scanning, não migrações, pooling de conexão ou política de transação.
Use migrações expandir-contrair: adicione colunas nullable, escreva em duplicidade, faça backfill e, em seguida, force NOT NULL em uma migração posterior.
sqlc suporta opções de driver pgx no código gerado - configure em sqlc.yaml de acordo com as necessidades do projeto.
Veja a seção de bancos de dados para padrões embed; a CLI migrate ainda precisa de um sistema de arquivos ou io.Source em tempo de execução.
Sim - protobuf verifica o formato de transmissão, não as regras de negócio; reutilize o validador ou faça verificações manuais em DTOs convertidos.
Testes orientados por tabela em validate.Struct com literais de DTO bons e ruins; nenhum banco de dados é necessário.
Registre traduções personalizadas no validator ou mapeie tags para chaves de local em seu mapeador de erros HTTP.
São higiene de entrada, não autorização - sempre aplique autorização nos serviços após a validação.
Versões da 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