# Como integrar validação de CPF em microserviços Go com Gin framework

> Aprenda a integrar a validação de CPF via API em microserviços Go usando Gin framework com exemplos completos, middleware e boas práticas.

**Publicado:** 20/02/2025
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/como-integrar-validacao-de-cpf-em-microservicos-go-com-gin-framework

---


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

```bash
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

```go
// 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

```go
// 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

```go
// 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:

```go
// 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

```go
// 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

```bash
# 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:

```bash
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 `/health` para 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](https://github.com/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.

### Leia também

- [Como validar CPF no frontend com React e API REST](https://cpfhub.io/blog/como-validar-cpf-no-frontend-com-react-e-api-rest)
- [SLA de API de CPF: níveis de disponibilidade e o que exigir do seu provedor](https://cpfhub.io/blog/sla-api-cpf-niveis-disponibilidade)
- [API de CPF grátis para desenvolvedores: como começar em 5 minutos](https://cpfhub.io/blog/api-cpf-gratis-desenvolvedores-comecar-5-minutos)
- [Como fazer fallback automático quando a API de CPF está fora do ar](https://cpfhub.io/blog/como-fazer-fallback-automatico-quando-a-api-de-cpf-esta-fora-do-ar)

---

## 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](https://www.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.

