Workspaces: desenvolvendo múltiplos módulos juntos
1. Introdução aos Workspaces no Go
Desenvolvedores Go frequentemente enfrentam o desafio de gerenciar múltiplos módulos interdependentes localmente. Antes dos workspaces, a solução comum era usar a diretiva replace no go.mod para apontar para diretórios locais — uma abordagem funcional, mas que poluía o arquivo de dependências e exigia alterações manuais constantes.
Um workspace no Go é um ambiente que permite desenvolver múltiplos módulos simultaneamente, resolvendo dependências locais de forma transparente. O coração dessa funcionalidade é o arquivo go.work, que define quais módulos fazem parte do workspace e como eles se relacionam.
A estrutura básica de um go.work é simples:
go 1.22
use (
./lib
./cmd
)
2. Configurando seu Primeiro Workspace
Criar um workspace é direto com o comando go work init. Suponha que temos dois módulos: lib e cmd.
// Estrutura de diretórios
/meu-projeto
├── lib/
│ └── go.mod
└── cmd/
└── go.mod
Para criar o workspace:
$ cd /meu-projeto
$ go work init ./lib ./cmd
Isso gera um arquivo go.work:
go 1.22
use (
./lib
./cmd
)
O comando go work use adiciona novos módulos ao workspace existente:
$ go work use ./api
As diretivas principais do go.work são:
- use: lista os diretórios dos módulos locais
- replace: substitui dependências específicas (similar ao
go.mod) - directory: caminho base para resolução de módulos
3. Estrutura de Projetos com Workspaces
Vamos construir um exemplo prático. Criaremos um módulo utilitário lib e um módulo principal cmd que o consome.
lib/go.mod:
module github.com/exemplo/lib
go 1.22
lib/strings.go:
package lib
import "strings"
func ToUpper(s string) string {
return strings.ToUpper(s)
}
func Reverse(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
cmd/go.mod:
module github.com/exemplo/cmd
go 1.22
require github.com/exemplo/lib v0.0.0
cmd/main.go:
package main
import (
"fmt"
"github.com/exemplo/lib"
)
func main() {
texto := "golang workspaces"
fmt.Println(lib.ToUpper(texto))
fmt.Println(lib.Reverse(texto))
}
Com o workspace configurado, o Go resolve automaticamente github.com/exemplo/lib para o diretório local ./lib, sem precisar de replace no go.mod.
A diferença crucial: o go.work gerencia a resolução local sem modificar os arquivos go.mod individuais, mantendo-os limpos para publicação.
4. Desenvolvimento e Iteração com Workspaces
A principal vantagem dos workspaces aparece durante o desenvolvimento ativo. Podemos editar código em lib e ver os resultados imediatamente em cmd sem rebuilds manuais.
$ # No diretório raiz do workspace
$ go build ./cmd
$ go test ./...
O comando go build dentro do workspace resolve as dependências localmente. Se você modificar a função Reverse em lib, o próximo build em cmd refletirá automaticamente a mudança.
Antes dos workspaces, cada módulo precisava de um replace manual:
// go.mod sem workspace
replace github.com/exemplo/lib => ../lib
Com workspaces, isso não é mais necessário. O workspace substitui completamente essa abordagem.
5. Gerenciamento de Dependências e Versões
Workspaces gerenciam dependências externas compartilhadas de forma inteligente. Se dois módulos no workspace usam a mesma biblioteca externa, o Go resolve para uma única versão.
// go.work
go 1.22
use (
./lib
./cmd
./api
)
replace github.com/exemplo/lib => ./lib
Para controlar versões de dependências locais vs. publicadas, use o go.work para desenvolvimento local e mantenha o go.mod para versões publicadas.
O comando go work sync sincroniza as dependências entre todos os módulos do workspace:
$ go work sync
Isso garante que todos os módulos usem as mesmas versões das dependências compartilhadas.
6. Trabalhando em Equipe com Workspaces
A decisão de versionar ou não o go.work depende do fluxo de trabalho da equipe:
Versionar o go.work (recomendado para times pequenos):
- Todos usam a mesma estrutura de módulos
- Facilita onboarding de novos membros
- CI/CD pode usar o mesmo workspace
Ignorar no .gitignore (recomendado para projetos grandes):
- Cada desenvolvedor tem sua estrutura local
- Evita conflitos de caminhos absolutos
- CI/CD usa replace ou módulos publicados
Exemplo de .gitignore:
go.work
go.work.sum
Para CI/CD, uma estratégia comum é:
# .github/workflows/ci.yml (exemplo)
steps:
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- run: go work init ./lib ./cmd
- run: go build ./cmd
- run: go test ./...
7. Migrando de replace para Workspaces
Projetos existentes frequentemente usam replace no go.mod. A migração é simples:
Antes:
// cmd/go.mod
module github.com/exemplo/cmd
go 1.22
require github.com/exemplo/lib v0.0.0
replace github.com/exemplo/lib => ../lib
Depois:
1. Remova os replace do go.mod
2. Crie o go.work com go work init ./cmd ./lib
$ go work init ./cmd ./lib
// go.work
go 1.22
use (
./cmd
./lib
)
// cmd/go.mod (limpo)
module github.com/exemplo/cmd
go 1.22
require github.com/exemplo/lib v0.0.0
Limitações: workspaces não substituem replace em cenários onde você precisa substituir dependências de dependências transitivas. Nesses casos, ainda use replace no go.work.
8. Considerações Finais e Boas Práticas
Armadilhas comuns:
- Caminhos absolutos: evite usar caminhos absolutos no
go.work; prefira relativos ao diretório do workspace - Módulos duplicados: se um módulo aparece em
usee também como dependência externa, o workspace prioriza a versão local - Esquecer o
go.work: sem o arquivo, os módulos tentarão resolver dependências externamente
Performance: workspaces com muitos módulos (10+) podem ter builds mais lentos. Considere dividir em workspaces menores.
Boas práticas:
- Mantenha o
go.workna raiz do projeto - Use
go work syncregularmente - Documente a estrutura do workspace para a equipe
- Considere versionar o
go.workpara projetos pequenos - Teste sempre com
go test ./...no workspace completo
Os workspaces representam uma evolução significativa na experiência de desenvolvimento Go, eliminando a necessidade de manipulação manual de replace e permitindo iteração mais rápida entre módulos interdependentes.
Referências
- Documentação Oficial: Workspaces no Go — Tutorial passo a passo da equipe oficial do Go sobre criação e uso de workspaces
- Go Blog: Getting started with Go workspaces — Anúncio oficial e guia detalhado sobre a funcionalidade de workspaces
- Go by Example: Workspaces — Exemplos práticos e concisos de configuração e uso de workspaces
- DigitalOcean: How to Use Go Workspaces — Tutorial abrangente com casos de uso reais e dicas de boas práticas
- Earthly.dev: Go Workspaces Guide — Guia técnico profundo sobre workspaces, incluindo estratégias para CI/CD e migração de projetos existentes
- GitHub: golang/go - Workspace proposal — Proposta original e discussão técnica sobre a implementação de workspaces no Go