Para integrar validação de CPF em um microserviço Go com Gin, crie um serviço dedicado que chama GET https://api.cpfhub.io/cpf/{CPF} com o header x-api-key, implemente um handler que expõe o resultado internamente e adicione middleware de rate limiting para controlar o consumo da cota mensal.
Introdução
O Gin é o framework web mais popular do ecossistema Go, conhecido pela sua performance excepcional e pela simplicidade de sua API. Em arquiteturas de microserviços, é comum ter um serviço dedicado à validação de identidade que consulta APIs externas para verificar dados cadastrais como o CPF.
Integrar a validação de CPF em um microserviço Go com Gin permite criar um ponto centralizado de verificação que pode ser consumido por outros serviços da arquitetura.
Pré-requisitos
- Go 1.21+ — Instalado e configurado.
- Conta na CPFHub.io — Para obter a chave de API (50 consultas/mês no plano gratuito, sem cartão).
Inicializando o projeto
mkdir cpf-service && cd cpf-service
go mod init cpf-service
go get github.com/gin-gonic/gin
Estrutura do projeto
cpf-service/
main.go
handlers/
cpf_handler.go
services/
cpf_service.go
models/
cpf.go
middleware/
rate_limiter.go
Modelos de dados
// models/cpf.go
package models
type CpfResponse struct {
Success bool `json:"success"`
Data CpfData `json:"data"`
}
type CpfData struct {
Cpf string `json:"cpf"`
Name string `json:"name"`
NameUpper string `json:"nameUpper"`
Gender string `json:"gender"`
BirthDate string `json:"birthDate"`
Day int `json:"day"`
Month int `json:"month"`
Year int `json:"year"`
}
type ErrorResponse struct {
Error string `json:"error"`
Code int `json:"code"`
}
Serviço de consulta
// services/cpf_service.go
package services
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"regexp"
"time"
"cpf-service/models"
)
type CpfService struct {
httpClient *http.Client
apiKey string
baseURL string
}
func NewCpfService(apiKey string) *CpfService {
return &CpfService{
httpClient: &http.Client{
Timeout: 10 * time.Second,
},
apiKey: apiKey,
baseURL: "https://api.cpfhub.io",
}
}
func (s *CpfService) Consultar(ctx context.Context, cpf string) (*models.CpfData, error) {
re := regexp.MustCompile(`\D`)
cpfLimpo := re.ReplaceAllString(cpf, "")
if len(cpfLimpo) != 11 {
return nil, fmt.Errorf("CPF inválido: informe 11 dígitos numéricos")
}
url := fmt.Sprintf("%s/cpf/%s", s.baseURL, cpfLimpo)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, fmt.Errorf("erro ao criar requisição: %w", err)
}
req.Header.Set("x-api-key", s.apiKey)
req.Header.Set("Accept", "application/json")
resp, err := s.httpClient.Do(req)
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
return nil, fmt.Errorf("tempo limite excedido")
}
return nil, fmt.Errorf("erro na requisição: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("erro ao ler resposta: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("erro HTTP %d", resp.StatusCode)
}
var cpfResp models.CpfResponse
if err := json.Unmarshal(body, &cpfResp); err != nil {
return nil, fmt.Errorf("erro ao decodificar resposta: %w", err)
}
if !cpfResp.Success {
return nil, fmt.Errorf("CPF não encontrado")
}
return &cpfResp.Data, nil
}
Handler HTTP
// handlers/cpf_handler.go
package handlers
import (
"net/http"
"cpf-service/models"
"cpf-service/services"
"github.com/gin-gonic/gin"
)
type CpfHandler struct {
service *services.CpfService
}
func NewCpfHandler(service *services.CpfService) *CpfHandler {
return &CpfHandler{service: service}
}
func (h *CpfHandler) Consultar(c *gin.Context) {
cpf := c.Param("cpf")
if cpf == "" {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
Error: "CPF não informado.",
Code: 400,
})
return
}
dados, err := h.service.Consultar(c.Request.Context(), cpf)
if err != nil {
status := http.StatusInternalServerError
if err.Error() == "CPF inválido: informe 11 dígitos numéricos" {
status = http.StatusBadRequest
} else if err.Error() == "CPF não encontrado" {
status = http.StatusNotFound
} else if err.Error() == "tempo limite excedido" {
status = http.StatusGatewayTimeout
}
c.JSON(status, models.ErrorResponse{
Error: err.Error(),
Code: status,
})
return
}
c.JSON(http.StatusOK, gin.H{
"valido": true,
"dados": dados,
})
}
Middleware de rate limiting
Para proteger o microserviço de excesso de requisições internas e controlar o consumo da cota mensal da CPFHub.io:
// middleware/rate_limiter.go
package middleware
import (
"net/http"
"sync"
"time"
"github.com/gin-gonic/gin"
)
type RateLimiter struct {
mu sync.Mutex
lastCall time.Time
interval time.Duration
}
func NewRateLimiter(interval time.Duration) *RateLimiter {
return &RateLimiter{
interval: interval,
}
}
func (rl *RateLimiter) Middleware() gin.HandlerFunc {
return func(c *gin.Context) {
rl.mu.Lock()
elapsed := time.Since(rl.lastCall)
if elapsed < rl.interval {
rl.mu.Unlock()
c.JSON(http.StatusTooManyRequests, gin.H{
"error": "Aguarde antes de realizar uma nova consulta.",
})
c.Abort()
return
}
rl.lastCall = time.Now()
rl.mu.Unlock()
c.Next()
}
}
Nota: esse rate limiting é aplicado pelo seu próprio microserviço para controlar o consumo interno da cota. A CPFHub.io não retorna HTTP 429 — ao exceder o limite mensal do plano, cada consulta extra é cobrada a R$0,15 sem interrupção do serviço.
Montando o servidor principal
// main.go
package main
import (
"log"
"os"
"time"
"cpf-service/handlers"
"cpf-service/middleware"
"cpf-service/services"
"github.com/gin-gonic/gin"
)
func main() {
apiKey := os.Getenv("CPFHUB_API_KEY")
if apiKey == "" {
apiKey = "SUA_CHAVE_DE_API"
}
cpfService := services.NewCpfService(apiKey)
cpfHandler := handlers.NewCpfHandler(cpfService)
rateLimiter := middleware.NewRateLimiter(2 * time.Second)
r := gin.Default()
api := r.Group("/api")
{
cpf := api.Group("/cpf")
cpf.Use(rateLimiter.Middleware())
{
cpf.GET("/:cpf", cpfHandler.Consultar)
}
}
r.GET("/health", func(c *gin.Context) {
c.JSON(200, gin.H{"status": "ok"})
})
log.Println("Servidor iniciado na porta 8080")
if err := r.Run(":8080"); err != nil {
log.Fatalf("Erro ao iniciar servidor: %v", err)
}
}
Testando o microserviço
# Iniciar o servidor
CPFHUB_API_KEY=SUA_CHAVE_DE_API go run main.go
# Em outro terminal, consultar CPF
curl -X GET http://localhost:8080/api/cpf/12345678900 \
-H "Accept: application/json" \
--max-time 10
Para testar diretamente a API da CPFHub.io:
curl -X GET https://api.cpfhub.io/cpf/12345678900 \
-H "x-api-key: SUA_CHAVE_DE_API" \
-H "Accept: application/json" \
--max-time 10
Boas práticas para microserviços
-
Health check — Inclua um endpoint
/healthpara monitoramento e orquestração (Kubernetes, Docker Swarm). -
Context propagation — Propague o context do Gin para o serviço para garantir cancelamento e timeout corretos.
-
Variáveis de ambiente — Armazene segredos em variáveis de ambiente, nunca no código.
-
Controle de consumo — Implemente rate limiting interno para não exceder a cota mensal do plano sem necessidade. O plano gratuito da CPFHub.io inclui 50 consultas/mês; o plano Pro oferece 1.000 por R$149/mês, com excedente a R$0,15.
-
Observabilidade — Adicione métricas (Prometheus), traces (OpenTelemetry) e logs estruturados para monitoramento em produção.
Perguntas frequentes
Por que centralizar a validação de CPF em um microserviço dedicado?
Um microserviço de validação evita que múltiplos serviços da arquitetura façam chamadas independentes à API externa, o que dispersa o controle de cotas, dificulta o monitoramento e aumenta a chance de falhas silenciosas. Com um ponto central, você aplica cache, rate limiting, logging e circuit breaker em um único lugar — qualquer mudança de provedor ou atualização de API key afeta apenas esse serviço.
Como implementar circuit breaker para proteger o microserviço de falhas na API externa?
A biblioteca sony/gobreaker é uma opção madura para Go. Configure o circuit breaker para abrir após um número configurável de falhas consecutivas (ex: 5), aguardar um intervalo de recuperação (ex: 30 segundos) e testar com uma requisição de prova antes de fechar. Durante o estado aberto, o serviço deve retornar o resultado do cache ou sinalizar degradação graceful em vez de propagar o erro.
O campo nameUpper da resposta da CPFHub.io é diferente de name?
Sim. O campo name retorna o nome com capitalização mista (ex: "João da Silva"), enquanto nameUpper retorna tudo em maiúsculas (ex: "JOÃO DA SILVA"). Para comparações de nome — como verificar divergências em cadastros — prefira usar nameUpper após converter o nome informado pelo usuário para maiúsculas, evitando falsos positivos por diferença de capitalização.
Como lidar com o timeout de ~900ms da API em contextos de alta concorrência?
Configure o http.Client com Timeout de 10 segundos para acomodar variações de latência. Em cenários de alta concorrência, implemente cache Redis com TTL de 24 horas para CPFs já consultados — a maioria das requisições será atendida localmente em menos de 1ms. Para picos previsíveis (ex: campanhas de cadastro), pré-aqueça o cache consultando os CPFs do público-alvo fora do horário de pico.
Conclusão
Construir um microserviço de validação de CPF com Go e Gin é uma abordagem eficiente que centraliza a lógica de verificação e pode ser consumida por toda a arquitetura de microserviços. Com cache, rate limiting interno e observabilidade, o serviço fica robusto para produção desde o primeiro deploy.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e integre a validação de CPF ao seu microserviço Go em menos de 30 minutos usando os exemplos deste guia.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



