Introdução: aspas mágicas no código Go
Se você já escreveu structs em Go para trabalhar com JSON, certamente já viu construções estranhas como estas:
type User struct { Name string `json:"name"` Age int `json:"age,omitempty"`}Essas misteriosas crases (`json:"name"`) são chamadas de struct tags (tags de struct). Para iniciantes, parecem mágica ou ruído desnecessário. Mas na verdade, são um dos recursos mais poderosos e elegantes do Go, permitindo metaprogramação sem macros complexos.
Neste artigo, vamos entender o que são struct tags em Go, para que servem, quais tipos existem e como usá-las em projetos reais. Você deixará de temer essas "strings mágicas" e passará a usá-las com consciência.
O que são struct tags? Explicação simples
Struct tags são literais de string escritos após o tipo de campo em uma struct. Eles são delimitados por crases (`) e representam pares chave:"valor".
Do ponto de vista da linguagem, as tags de struct em Go são apenas texto. O compilador Go não as analisa nem valida. Seu significado só aparece quando você (ou uma biblioteca) as lê através do pacote reflect.
Simplificando: tags são metadados que você anexa aos campos da struct. Outras partes do seu programa podem ler esses metadados e alterar seu comportamento.
Para que servem as struct tags? 3 cenários principais
1. Serialização/desserialização (JSON, XML, YAML)
Este é o caso de uso mais comum e compreensível. Imagine que você tem uma struct Go e quer transformá-la em JSON (ou vice-versa).
type User struct { ID int `json:"id"` FirstName string `json:"first_name"` LastName string `json:"last_name"` Password string `json:"-"`}
func main() { user := User{ID: 1, FirstName: "João", LastName: "Silva", Password: "secreto"} jsonData, _ := json.Marshal(user) fmt.Println(string(jsonData)) // Saída: {"id":1,"first_name":"João","last_name":"Silva"} // A senha não aparece no JSON, porque a tag é json:"-"}Sem tags, os campos seriam chamados ID, FirstName, etc., o que não segue o estilo JSON (camelCase vs snake_case). As struct tags do Golang para JSON permitem controlar:
- O nome do campo no JSON
- Omissão de campos vazios (
omitempty) - Exclusão de campos da saída (
-) - Opções aninhadas
2. Validação de dados
Bibliotecas populares como go-playground/validator usam struct tags do Go para validação. Você simplesmente escreve as regras diretamente na struct:
type SignUpRequest struct { Email string `validate:"required,email"` Password string `validate:"required,min=8,max=32"` Age int `validate:"gte=18,lte=120"`}
func validateUser(user SignUpRequest) error { validate := validator.New() err := validate.Struct(user) return err}Isso é incrivelmente conveniente: as regras de validação ficam próximas aos dados, e não espalhadas pelo código. Struct tags para validação tornam o código autodocumentável.
3. Trabalho com bancos de dados (ORM)
Bibliotecas ORM (GORM, Ent, SQLBoiler) usam ativamente struct tags para ORM. Por exemplo, no GORM:
type Product struct { gorm.Model Code string `gorm:"uniqueIndex;not null"` Price uint `gorm:"default:0"` UserID uint `gorm:"foreignKey:UserID"`}As tags gorm definem índices, restrições, chaves estrangeiras e outras configurações de tabela. Isso elimina a necessidade de escrever migrações separadas.