Handling JSON Post Request em Go: por que até desenvolvedores experientes caem em armadilhas
\n\nVocê já escreveu um servidor em Go que precisa receber JSON via requisição POST e, de repente, obteve uma estrutura vazia ou um erro fatal? Se sim — você não está sozinho. A pergunta "Handling JSON Post Request in Go" no Stack Overflow acumulou dezenas de milhares de visualizações e centenas de respostas. Este é um verdadeiro "ponto de dor" da comunidade.
\n\nNeste artigo, não vamos apenas analisar como processar corretamente requisições JSON POST. Vamos percorrer os principais erros que iniciantes e até profissionais cometem. Você aprenderá como evitar erros típicos, escrever código limpo e não perder horas em depuração. Vamos lá!
\n\nPor que JSON e Go são amor à primeira vista?
\n\nGo (ou Golang) foi criado para serviços web modernos. O pacote embutido encoding/json é uma ferramenta poderosa. Mas, como qualquer ferramenta poderosa, requer manuseio adequado. O problema mais comum é a incompatibilidade entre o JSON enviado pelo cliente e a estrutura que o servidor espera.
Vamos começar pela base — a estrutura correta do manipulador.
\n\nErro nº1: Esquecer de fechar o corpo da requisição
\n\nA primeira coisa que você deve fazer em qualquer manipulador POST é fechar obrigatoriamente o corpo da requisição. Isso não é apenas boa educação, é a garantia de que seu servidor não vazará memória.
\n\npackage main\n\nimport (\n "encoding/json"\n "net/http"\n)\n\ntype User struct {\n Name string `json:"name"`\n Email string `json:"email"`\n}\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n // IMPORTANTE: fechar o Body\n defer r.Body.Close()\n\n // ... resto do código\n}\n\nMuitos iniciantes pulam esta linha, e o servidor começa a "consumir" memória. Sempre use defer r.Body.Close() imediatamente após receber a requisição.
Erro nº2: Ignorar a verificação do método da requisição
\n\nSeu manipulador deve verificar explicitamente se veio um POST, e não um GET ou PUT. Caso contrário, você corre o risco de obter um pânico ou comportamento estranho.
\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n defer r.Body.Close()\n\n if r.Method != http.MethodPost {\n http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)\n return\n }\n\n // ... agora trabalhamos com JSON\n}\n\nEsta regra simples evitará muitas dores de cabeça. Sempre verifique o método — é a higiene básica do código.
\n\nErro nº3: Usar um decodificador JSON não rigoroso
\n\nPor padrão, o json.Decoder em Go não lança erro se o JSON tiver campos extras que não estão descritos na sua estrutura. Isso pode levar a "engolir" dados inválidos.
A receita para evitar isso é usar json.Decoder com a opção DisallowUnknownFields:
func handler(w http.ResponseWriter, r *http.Request) {\n defer r.Body.Close()\n\n var user User\n\n decoder := json.NewDecoder(r.Body)\n // Ativando modo rigoroso\n decoder.DisallowUnknownFields()\n\n err := decoder.Decode(&user)\n if err != nil {\n http.Error(w, "Invalid JSON: "+err.Error(), http.StatusBadRequest)\n return\n }\n\n // Se o JSON tiver campos extras — receberemos um erro\n // Isso é uma proteção contra erros de digitação acidentais na API\n\n w.WriteHeader(http.StatusOK)\n json.NewEncoder(w).Encode(user)\n}\n\nEsta abordagem é especialmente útil quando você desenvolve uma API pública. Os clientes agradecerão por erros claros.
\n\nErro nº4: Não verificar se o JSON não está vazio
\n\nImagine: o cliente envia um corpo de requisição vazio. Seu código decodifica sem problemas um JSON vazio {} e cria uma estrutura com valores zero. Isso pode não ser o que você espera.
A melhor prática é verificar se o corpo não está vazio e se todos os campos obrigatórios estão preenchidos:
\n\nfunc hand