Monorepositório com Go: organização de código na prática

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Monorepositório com Go: organização de código na prática

\n\n

Monorepositório (monorepo) é uma abordagem para gerenciamento de código-fonte onde todos os projetos, bibliotecas e serviços são armazenados em um único repositório. No mundo Go, essa abordagem se tornou especialmente popular devido ao suporte nativo a módulos e ao sistema flexível de pacotes. Neste artigo, vamos explorar como organizar um monorepositório em Go na prática, analisar uma estrutura típica, exemplos de código e melhores práticas.

\n\n

Por que um monorepositório em Go?

\n\n

O monorepositório resolve várias tarefas principais:

\n
    \n
  • Simplificação do gerenciamento de dependências — todos os pacotes internos estão em um só lugar, facilitando atualizações e refatorações.
  • \n
  • Histórico unificado de alterações — commits atômicos que afetam vários serviços funcionam sem sincronizações extras.
  • \n
  • Aceleração do CI/CD — é possível configurar pipelines que compilam apenas as partes alteradas do projeto.
  • \n
  • Melhoria da qualidade do código — é mais fácil implementar padrões unificados, linters e code reviews.
  • \n
\n\n

Estrutura do monorepositório Go: esquema básico

\n\n

Vamos analisar uma estrutura típica de monorepositório em Go. Como exemplo, considere um projeto composto por dois microsserviços (api e worker) e uma biblioteca compartilhada lib:

\n\n
my-monorepo/\n├── go.work\n├── go.work.sum\n├── apps/\n│   ├── api/\n│   │   ├── go.mod\n│   │   ├── main.go\n│   │   └── handler.go\n│   └── worker/\n│       ├── go.mod\n│       ├── main.go\n│       └── process.go\n├── lib/\n│   ├── go.mod\n│   ├── auth/\n│   │   └── auth.go\n│   └── db/\n│       └── db.go\n├── scripts/\n│   ├── build.sh\n│   └── test.sh\n└── Makefile
\n\n

Elementos principais:

\n
    \n
  • go.work — arquivo de workspace do Go (Workspace) que conecta todos os módulos.
  • \n
  • apps/ — diretório com aplicações (microsserviços, utilitários CLI, etc.).
  • \n
  • lib/ — bibliotecas compartilhadas usadas por todas as aplicações.
  • \n
  • scripts/ — scripts auxiliares para compilação, teste e deploy.
  • \n
\n\n

Configuração do Go Workspace (go.work)

\n\n

Go 1.18+ fornece o mecanismo workspace, que permite trabalhar com vários módulos simultaneamente. Vamos criar o arquivo go.work na raiz:

\n\n
go 1.22\n\nuse (\n    ./apps/api\n    ./apps/worker\n    ./lib\n)
\n\n

Agora, durante o desenvolvimento, é possível executar comandos a partir da raiz do projeto, e o Go enxergará todos os módulos como um todo. Por exemplo, para executar os testes de todos os módulos:

\n\n
go test ./...
\n\n

E para compilar um serviço específico:

\n\n
cd apps/api && go build -o bin/api .
\n\n

Exemplo de código: biblioteca compartilhada e microsserviço

\n\n

Vamos criar uma biblioteca simples de autenticação em lib/auth/auth.go:

\n\n
package auth\n\nimport "errors"\n\nvar (\n    ErrInvalidToken = errors.New("invalid token")\n)\n\n// ValidateToken verifica o token e retorna o ID do usuário.\nfunc ValidateToken(token string) (string, error) {\n    if token == "" {\n        return "", ErrInvalidToken\n    }\n    // Aqui pode haver uma verificação real de JWT ou chamada a um serviço externo\n    return "user-123", nil\n}
\n\n

Agora, vamos usar esta biblioteca no microsserviço apps/api/handler.go:

\n\n
package main\n\nimport (\n    "encoding/json"\n    "net/http"\n    "my-monorepo/lib/auth"\n)\n\ntype UserResponse struct {\n    UserID string `json:"user_id"`\n}\n\nfunc UserHandler(w http.ResponseWriter, r *http.Request) {\n    token := r.Header.Get("Authorization")\n    userID, err := auth.ValidateToken(token)\n    if err != nil {\n        http.Error(w, "Unauthorized", http.StatusUnauthorized)\n        return\n    }\n\n    resp := UserResponse{UserID: user                

Blogs

Book Recommendations