M02·10Exercícios

CAPÍTULO 10

Exercícios

Doze exercícios progressivos do servidor HTTP mínimo ao graceful shutdown, cache decorator e idempotência.

Por Thiago Souza6 min de leituraAtualizado em 2026-05

Resolva na ordem — cada um aprofunda o anterior. Tente resolver sem consultar a solução.

Nível 1 — Básico

1. Estrutura mínima. Crie um projeto Go com cmd/api/main.go que sobe um servidor HTTP em :8080 respondendo "ok" no endpoint GET /health. Use slog para logar o início do servidor.

2. CRUD em memória. Adicione um endpoint GET /tasks e POST /tasks que armazena tarefas em um map em memória, protegido por sync.Mutex. (Sim, vai sumir tudo quando reiniciar — o ponto é treinar a separação de camadas.)

3. Camadas. Refatore o exercício 2 separando em três pacotes: task (entity + service), http (handler), e memory (repositório em memória). Defina task.Repository como interface.

Nível 2 — Intermediário

4. Postgres. Crie um adapter Postgres que implementa task.Repository. Use pgx. Crie a migration. Faça o main.go escolher entre o repositório de memória e o de Postgres com base em uma variável de ambiente STORAGE=memory|postgres.

5. Validação rica. Adicione validação que verifica:

  • título tem entre 3 e 200 caracteres;
  • descrição tem no máximo 2000 caracteres;
  • cada erro de validação retorna mensagem específica para o cliente (HTTP 422).

6. Listagem paginada. GET /tasks?limit=10&offset=20. Saneie os parâmetros (sem números negativos, limite máximo de 100).

7. Testes unitários do service. Escreva pelo menos 6 casos de teste cobrindo cenários de sucesso e erro. Não suba banco — use fake repository.

Nível 3 — Avançado

8. Cache decorator. Implemente um CachedTaskRepo que decora o repositório de Postgres com Redis (cache-aside). Garanta que o Update e o Delete invalidem o cache. Adicione TTL de 5 minutos.

9. Métricas Prometheus. Adicione um middleware HTTP que registra:

  • contador de requests por método e status;
  • histograma de latência por rota. Exponha /metrics.

10. Graceful shutdown. Faça o servidor responder a SIGINT e SIGTERM parando de aceitar conexões novas, terminando as em andamento (com timeout de 30s) e fechando o pool de banco antes de sair. Dica: signal.NotifyContext + srv.Shutdown(ctx).

11. Teste de integração com Postgres real. Use testcontainers-go para subir um Postgres descartável durante os testes do postgres.TaskRepo. Rode as migrations no setup. Limpe entre testes.

12. Idempotência. Implemente o endpoint POST /tasks aceitando um header Idempotency-Key. Se a mesma chave for enviada de novo dentro de 24 horas, retorne a mesma resposta da primeira vez (use Redis para guardar). Isso é o que evita pedido duplicado quando o app do cliente faz retry.

Nível 4 — Bônus de Arquitetura

13. Troca a engrenagem. Sem mexer no pacote task, troque o transporte HTTP por gRPC. Se você fez tudo direito, isso é só criar um novo adapter na pasta internal/grpc/ e amarrar no main.go. Se você precisou mexer no service, havia acoplamento escondido — ache e remova.

Não tente resolver todos os exercícios de uma vez. Faça os do Nível 1 primeiro, suba um servidor que funciona de ponta a ponta, depois vá adicionando camadas.