Monorepositório com Go: organização de código para projetos escaláveis
No desenvolvimento de software moderno, surge cada vez mais a questão: como organizar o código para que ele permaneça gerenciável, reutilizável e escalável? Uma das soluções populares é o uso de monorepositório (monorepo) — um repositório único contendo vários projetos ou serviços. Neste artigo, vamos analisar como organizar eficientemente um monorepositório em Go (Golang), abordar as melhores práticas, estrutura de diretórios, trabalho com módulos e configuração de CI/CD.
O que é um monorepositório e por que ele é necessário em Go?
Monorepositório é uma abordagem onde todo o código de uma empresa ou grande projeto é armazenado em um único repositório. Isso pode incluir:
- Vários microsserviços
- Bibliotecas e utilitários
- Configurações e scripts
- Documentação
Vantagens do monorepositório para Go:
- Versão única de dependências — elimina conflitos de versão entre serviços.
- Simplificação de refatoração — alterações em uma biblioteca comum são imediatamente visíveis para todos os consumidores.
- Reutilização fácil de código — não é necessário publicar pacotes em um registry.
- Histórico único de commits — simplifica depuração e auditoria.
No entanto, o monorepositório exige disciplina: sem uma estrutura clara, ele rapidamente se transforma em um "depósito de lixo". Go, com seu sistema rigoroso de módulos (Go Modules), oferece excelentes ferramentas para organizar esse tipo de repositório.
Estrutura de diretórios em um monorepositório Go
Uma estrutura correta é a base do sucesso. Vejamos a organização recomendada para um monorepositório em Go:
my-monorepo/├── apps/ # Aplicações (serviços, utilitários CLI)│ ├── api-gateway/│ │ ├── cmd/│ │ │ └── main.go│ │ ├── internal/│ │ ├── go.mod│ │ └── go.sum│ ├── auth-service/│ │ └── ...│ └── user-service/│ └── ...├── libs/ # Bibliotecas comuns│ ├── common/│ │ ├── logger.go│ │ ├── config.go│ │ ├── go.mod│ │ └── go.sum│ └── models/│ ├── user.go│ ├── go.mod│ └── go.sum├── scripts/ # Scripts de build, deploy│ ├── build.sh│ └── deploy.sh├── docs/ # Documentação├── .github/ # Configurações de CI/CD│ └── workflows/│ └── ci.yml├── go.work # Arquivo Workspace (Go 1.18+)├── Makefile # Comandos comuns├── README.md└── .gitignoreElementos-chave da estrutura:
- apps/ — contém aplicações executáveis (serviços, utilitários). Cada aplicação é um módulo Go separado com seu próprio
go.mod. - libs/ — bibliotecas comuns reutilizadas entre as aplicações.
- go.work — arquivo workspace que permite trabalhar com todos os módulos localmente sem publicar alterações.
Trabalhando com Go Modules em um monorepositório
A partir do Go 1.18, foi adicionado suporte para workspaces (go.work). Isso resolve o problema de desenvolvimento local quando os módulos dependem uns dos outros. Vejamos um exemplo de configuração.
Criaremos um arquivo go.work na raiz do monorepositório:
go 1.21
use ( ./apps/api-gateway ./apps/auth-service ./libs/common ./libs/models)Agora, durante o desenvolvimento local, o Go usará as versões locais dos módulos, em vez das publicadas. Isso é criticamente importante para iteração rápida.
Exemplo de dependência em apps/auth-service/go.mod:
module github.com/company/auth-service
go 1.21
require ( github.com/company/libs/common v0.0.0 github.com/company/libs/model