Monorepositório com Go: organização eficiente de código
No desenvolvimento de software moderno, a escolha da estratégia de gerenciamento de código é um dos principais fatores que afetam a produtividade da equipe e a escalabilidade do projeto. Monorepositório (monorepo) é uma abordagem onde o código de todos os serviços, bibliotecas e ferramentas é armazenado em um único repositório. Em combinação com a linguagem Go, que foi originalmente projetada para grandes projetos, o monorepositório se torna uma ferramenta poderosa.
Neste artigo, vamos analisar como organizar corretamente um monorepositório em Go: desde a estrutura básica de diretórios até o gerenciamento de dependências com Go Workspace. Você aprenderá como evitar erros típicos e construir uma arquitetura que crescerá junto com seu projeto.
Por que monorepositório e Go são a combinação ideal?
Go (Golang) é conhecido por sua simplicidade e eficiência. No entanto, ao trabalhar com microsserviços ou grandes bibliotecas, surge a questão: como organizar o código para que ele permaneça fácil de manter e refatorar?
Vantagens do monorepositório para Go:
- Versão única de dependências: todos os serviços usam as mesmas versões de bibliotecas, eliminando conflitos.
- Refatoração simplificada: alterações em uma API de uma biblioteca são refletidas imediatamente em todos os consumidores.
- Integridade dos commits: alterações em diferentes partes do projeto podem ser combinadas em um único commit, facilitando o rollback.
- Padronização: regras únicas de linting, teste e CI/CD para todo o projeto.
Além disso, Go oferece ferramentas integradas — módulos (go mod) e workspace (go work) — que são ideais para trabalhar com monorepositórios.
Estrutura básica de um monorepositório em Go
Uma estrutura de diretórios correta é a base de um monorepositório bem-sucedido. Vamos considerar a organização recomendada usando o exemplo de um projeto com vários microsserviços e uma biblioteca compartilhada.
myproject/├── apps/│ ├── api-gateway/│ │ ├── cmd/│ │ │ └── main.go│ │ ├── internal/│ │ ├── go.mod│ │ └── go.sum│ ├── user-service/│ │ ├── cmd/│ │ └── internal/│ └── order-service/│ ├── cmd/│ └── internal/├── libs/│ ├── common/│ │ ├── logger/│ │ ├── config/│ │ ├── go.mod│ │ └── go.sum│ └── db/│ ├── models/│ ├── migrations/│ ├── go.mod│ └── go.sum├── scripts/│ ├── build.sh│ └── deploy.sh├── go.work├── Makefile├── .golangci.yml└── README.mdExplicações sobre a estrutura:
apps/— contém aplicações executáveis (microsserviços, utilitários CLI). Cada serviço é um módulo Go separado com seu própriogo.mod.libs/— bibliotecas de uso geral que são reutilizadas entre os serviços.scripts/— scripts auxiliares para build, teste e deploy.go.work— arquivo workspace que conecta todos os módulos em um único espaço de desenvolvimento.
Importante: não coloque código diretamente na raiz do repositório. Use subdiretórios para agrupar por função.
Gerenciamento de dependências com Go Workspace
A partir da versão Go 1.18, foi adicionado suporte para workspace (área de trabalho). Este é um recurso chave para monorepositórios, permitindo desenvolver vários módulos simultaneamente sem a necessidade de publicá-los em um registro remoto.
Criação do workspace:
# Inicializar workspace na raiz do projetogo work init ./apps/api-gateway ./apps/user-service ./libs/common
# Adicionar um novo módulogo work use ./apps/order-service
# Visualizar o workspace atualgo work edit -jsonConteúdo do arquivo go.work:
```