Tags de Struct para JSON, Banco de Dados e Validação
Structs de produção frequentemente carregam três namespaces de tags em um único campo: json para APIs, db ou chaves específicas de ORM para armazenamento e validate para regras de entrada.
Busque em todas as páginas da documentação
Structs de produção frequentemente carregam três namespaces de tags em um único campo: json para APIs, db ou chaves específicas de ORM para armazenamento e validate para regras de entrada.
Nomes consistentes entre as tags mantêm serializadores, scanners SQL e validadores alinhados sem camadas DTO duplicadas.
Tags de struct são metadados de string anexados a campos, lidos via reflection em tempo de execução.
Cada biblioteca analisa sua própria chave (json, db, validate, xml, yaml, etc.).
Uma única struct pode servir às camadas HTTP e de banco de dados quando as tags concordam sobre o significado do campo, mas diferem nos nomes de fio/coluna.
Cartão de receita de referência rápida - pronto para copiar e colar.
type User struct {
ID int64 `json:"id" db:"id" validate:"required"`
Email string `json:"email" db:"email" validate:"required,email"`
Nickname *string `json:"nickname,omitempty" db:"nickname" validate:"omitempty,min=2,max=32"`
CreatedAt time.Time `json:"created_at" db:"created_at" validate:"-"`
Internal string `json:"-" db:"internal_note" validate:"-"`
}Quando usar isso:
package main
import (
"encoding/json"
"fmt"
"time"
)
type Product struct {
SKU string `json:"sku" db:"sku" validate:"required,alphanum"`
Title string `json:"title" db:"title" validate:"required,min=3,max=120"`
PriceCents int64 `json:"price_cents" db:"price_cents" validate:"gte=0"`
Active bool `json:"active" db:"is_active" validate:"-"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at" validate:"-"`
}
func main() {
p := Product{
SKU: "ABC123",
Title: "Wrench",
PriceCents: 1299,
Active: true,
UpdatedAt: time.Now().UTC(),
}
b, _ := json.Marshal(p)
fmt.Println(string(b))
// A tag db é ignorada pelo encoding/json; sqlx/jmoiron/sql usaria db:"sku" no Scan
// As tags validate são consumidas pelo go-playground/validator após o Unmarshal
}O que isso demonstra:
db nomeiam colunas para sqlx, scany ou scanners semelhantes.validate expressam regras separadas da serialização.json:"-" oculta campos da saída da API enquanto db ainda pode persistí-los.Tags são strings entre crases: `chave:"valor" outra:"valor"`.
Vírgulas dentro de um valor geralmente são opções: validate:"omitempty,min=1".
Chaves desconhecidas são ignoradas por cada biblioteca.
| Chave | Consumidor | Propósito |
|---|---|---|
json | encoding/json | Nome na rede, omitempty, - |
db | sqlx, scany | Nome da coluna |
validate | go-playground/validator | Regras de entrada |
xml | encoding/xml | Nome do elemento/atributo |
yaml | yaml.v3 | Arquivos de configuração |
form | gin/echo binders | Formulários HTML |
ORMs como GORM usam suas próprias tags de struct (gorm:"column:...") - escolha um estilo de persistência por projeto.
| Camada | Convenção | Campo de exemplo CreatedAt |
|---|---|---|
| Campo Go | PascalCase | CreatedAt |
| JSON | snake_case (comum) | created_at |
| Coluna SQL | snake_case | created_at |
Documente exceções (colunas legadas, camelCase JSON) em ADRs.
| Abordagem | Prós | Contras |
|---|---|---|
| Struct única com múltiplas tags | Menos código repetitivo | Acopla a API ao esquema |
| Modelos de API/DB separados | Limites claros | Mais código de mapeamento |
| Base incorporada + wrappers | IDs/timestamps compartilhados | Conflitos de tags se descuidado |
Comece com struct única para serviços pequenos; divida quando a versão da API divergir das tabelas.
// Lint: mantenha os nomes json e db alinhados, a menos que o esquema legado difira
// validate:"-" ignora a validação para timestamps definidos pelo servidorVerificadores de tags do golangci-lint (quando habilitados) sinalizam nomes de campos JSON incompatíveis com nomes de campos Go.
encoding/json. Correção: exporte campos de API ou use marshaler personalizados.validator.Struct. Correção: valide nos manipuladores após Unmarshal.database/sql sozinho ignora tags db. Correção: use sqlx/scany ou listas de colunas explícitas.omitempty; ponteiros nil omitem. Correção: modele números opcionais como ponteiros quando 0 for significativo.db causa scans NULL silenciosos. Correção: testes de integração para repositórios.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Struct única com múltiplas tags | Serviços CRUD com formas alinhadas | API pública muito diferente do esquema |
| DTOs separados por camada | APIs versionadas, joins complexos | Scripts pontuais |
| Geração de código (sqlc, buf) | Esquemas grandes | Protótipos únicos |
map[string]any | Ferramentas de administração dinâmicas | Contratos estáveis |
Frequentemente, eles correspondem por ergonomia do desenvolvedor.
Bancos de dados legados podem forçar tags db diferentes - documente esses campos.
Após a decodificação JSON em manipuladores HTTP ou após a vinculação de formulário.
Não durante json.Marshal, a menos que você adicione um pipeline personalizado.
Ferramentas como sqlc geram structs com tags a partir de consultas.
Modelos escritos manualmente exigem disciplina manual.
Use tags bson com as structs do driver oficial.
O mesmo padrão de múltiplas tags se aplica.
form:"email" suporta vinculação de consulta e multipart.
Mantenha json e form alinhados quando a mesma struct servir a ambos.
Sim, para segredos e colunas apenas de junção.
Certifique-se de que os logs usem um DTO com redação se a struct completa for impressa.
A geração de código Protobuf usa campos de struct gerados a partir de .proto - não tags json.
Gateways podem adicionar nomes JSON separadamente.
Habilite linters de alinhamento de tags em golangci-lint onde disponíveis.
Listas de verificação de revisão de código também capturam desvios.
validate:"omitempty,email" ignora strings vazias, mas valida valores presentes.
Campos promovidos herdam tags do tipo incorporado.
Sobrescritas externas prevalecem em conflitos de nomes - teste a saída JSON.
Versões da Stack: Esta página foi escrita para Go 1.26.x (Padrão GC Green Tea, go fix modernizers - verifique o patch na compilação), chi (última - verifique na compilação), gin (última - verifique na compilação), echo (última - verifique na compilação), google.golang.org/grpc (última - verifique na compilação), sigs.k8s.io/controller-runtime (última - verifique na compilação), kubebuilder (última - verifique na compilação), tinygo (última - verifique os alvos de placa na compilação), wazero (última - verifique na compilação) e golangci-lint (última - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 18 de jul. de 2026