Resposta rápida: use Go Workspaces quando você precisa alterar e testar dois ou mais módulos Go ao mesmo tempo. Na raiz do trabalho, rode go work init, adicione os módulos com go work use e execute os comandos normalmente. O arquivo go.work faz o toolchain resolver os imports pelo código local, sem publicar versões provisórias e sem espalhar replace ../outro-modulo pelos arquivos go.mod. Ele é especialmente útil em monorepos, na evolução conjunta de uma biblioteca e uma API e na reprodução local de mudanças que atravessam repositórios.
O recurso não transforma vários módulos em um único projeto. Cada diretório continua com seu próprio go.mod, suas dependências e seu ciclo de versão. O workspace é uma camada de desenvolvimento por cima desses módulos.
Quando usar go.work
Um workspace resolve um problema específico: o módulo app depende de lib, você está mudando os dois, mas a nova versão de lib ainda não existe em um proxy de módulos.
Sem workspace, as alternativas comuns são:
- publicar uma versão provisória da biblioteca;
- editar o
go.modda aplicação com umreplacepara um caminho local; - copiar código entre projetos;
- esperar a mudança da biblioteca ser publicada antes de testar a aplicação.
Com go.work, o código local entra na resolução sem modificar o go.mod que será consumido por outras pessoas.
| Situação | Go Workspace ajuda? | Motivo |
|---|---|---|
| Monorepo com várias APIs e bibliotecas | Sim | Permite desenvolver e testar módulos juntos |
| Biblioteca e aplicação em clones vizinhos | Sim | Liga os módulos locais sem publicar uma versão |
| Projeto com um único módulo | Geralmente não | Um go.mod já resolve o caso |
| Dependência externa sem mudanças locais | Não | Use a versão normal declarada no go.mod |
| Fork permanente de uma dependência | Talvez | Um replace versionado pode expressar melhor a decisão |
| Pacotes internos de uma única aplicação | Não necessariamente | Antes de criar módulos, considere manter apenas pacotes |
A última linha é importante. Nem todo diretório merece um módulo. Criar muitos go.mod aumenta o trabalho de versionamento, atualização e CI. Use múltiplos módulos quando existem fronteiras reais: publicação independente, consumidores diferentes, restrições de dependência ou ciclos de release separados.
Se você ainda está consolidando esses conceitos, comece pelo guia de Go Modules na prática e pela referência de módulos e dependências em Go.
Exemplo: uma API e uma biblioteca local
Imagine esta estrutura:
plataforma/
├── api/
│ ├── go.mod
│ └── main.go
└── saudacao/
├── go.mod
└── saudacao.go
A biblioteca possui seu próprio módulo:
// saudacao/saudacao.go
package saudacao
import "fmt"
func Ola(nome string) string {
return fmt.Sprintf("Olá, %s!", nome)
}
// saudacao/go.mod
module example.com/plataforma/saudacao
go 1.27
A API importa a biblioteca pelo caminho normal do módulo:
// api/main.go
package main
import (
"fmt"
"example.com/plataforma/saudacao"
)
func main() {
fmt.Println(saudacao.Ola("Gopher"))
}
// api/go.mod
module example.com/plataforma/api
go 1.27
require example.com/plataforma/saudacao v0.0.0
A versão v0.0.0 representa aqui uma dependência ainda não publicada. Na raiz plataforma, crie o workspace:
cd plataforma
go work init ./api ./saudacao
go run ./api
O comando gera um arquivo parecido com este:
// go.work
go 1.27
use (
./api
./saudacao
)
A partir desse diretório ou de seus subdiretórios, o comando go encontra go.work, reconhece os dois módulos e usa a implementação local de saudacao.
Comandos essenciais do go work
go work init
Cria o arquivo inicial:
go work init
Você pode informar módulos no mesmo comando:
go work init ./api ./libs/auth ./libs/observabilidade
Os caminhos devem apontar para diretórios que possuem go.mod.
go work use
Adiciona ou remove módulos da diretiva use:
go work use ./libs/pagamentos
go work use -r ./services
Com -r, o comando percorre recursivamente o diretório e adiciona os módulos encontrados. Isso é prático em um monorepo, mas revise o diff: incluir ferramentas, exemplos ou módulos experimentais sem intenção pode deixar todos os comandos mais amplos e lentos.
Para remover uma diretiva explicitamente, use go work edit:
go work edit -dropuse=./libs/legado
Outra opção é apagar ou mover o diretório e rodar go work use novamente: o comando remove entradas cujos módulos já não existem.
go work edit
Edita o arquivo de forma programática. É útil em scripts que não devem manipular texto com sed:
go work edit -use=./libs/catalogo
go work edit -dropuse=./libs/legado
go work edit -json
A saída JSON ajuda ferramentas internas a inspecionar o workspace sem depender da formatação textual.
go work sync
Sincroniza informações da lista de build do workspace com os módulos:
go work sync
Esse comando pode atualizar requisitos nos arquivos go.mod dos módulos. Por isso, não o trate como uma operação invisível: execute, revise os diffs e rode os testes. Ele não substitui o go mod tidy de cada módulo.
Como o Go encontra o arquivo go.work
Ao executar um comando, o toolchain procura go.work no diretório atual e depois sobe pelos diretórios pais. Você pode confirmar qual arquivo está ativo com:
go env GOWORK
A saída pode ser:
/home/ana/projetos/plataforma/go.work
Se não houver workspace ativo, o valor fica vazio ou indica que ele foi desabilitado, dependendo do ambiente.
Para ignorar o workspace em um único comando:
GOWORK=off go test ./...
Também é possível apontar explicitamente para um arquivo:
GOWORK=/tmp/workspaces/release.work go test ./...
O caminho explícito deve ser absoluto. Na prática, GOWORK=off é o caso mais importante: ele verifica se um módulo não depende acidentalmente do contexto local.
go.work não substitui go.mod
O go.mod continua sendo a declaração do módulo. Ele informa:
- o caminho público do módulo;
- a versão mínima da linguagem e do toolchain aplicável;
- as dependências necessárias;
- exclusões, retrações ou substituições relevantes ao módulo.
O go.work informa quais módulos principais locais participam da operação atual. Ele não deve ser usado para esconder que uma aplicação esqueceu de declarar uma dependência.
Uma verificação útil é rodar os testes de duas maneiras:
# Integração com todos os módulos locais do workspace
go test ./...
# Módulo isolado, usando apenas seu go.mod
cd api
GOWORK=off go test ./...
O primeiro comando responde: “as mudanças locais funcionam juntas?”. O segundo responde: “o módulo publicado continua reproduzível sozinho?”. Em uma base com releases independentes, você precisa das duas respostas.
go.work ou replace: qual escolher?
Uma diretiva replace no go.mod pode mapear um módulo para outro caminho ou versão:
replace example.com/plataforma/saudacao => ../saudacao
Isso funciona, mas um caminho relativo local tem dois riscos:
- pode ser commitado por acidente e quebrar o build de outra pessoa;
- mistura uma conveniência do ambiente de desenvolvimento com o contrato do módulo.
O workspace evita esses problemas porque concentra a ligação local em go.work.
Use go.work quando a substituição existe porque você está desenvolvendo módulos juntos. Considere replace quando o próprio módulo precisa expressar uma troca controlada, por exemplo um fork temporário fixado em uma versão ou um caso de compatibilidade que deve valer para todos os colaboradores. Mesmo assim, documente a decisão e planeje sua remoção.
O que é go.work.sum
Assim como um módulo pode ter go.sum, o workspace pode gerar go.work.sum. Ele registra hashes necessários para dependências usadas no contexto do workspace que não estejam cobertas pelos arquivos go.sum dos módulos.
Não edite esse arquivo manualmente. O comando go o mantém conforme resolve e baixa módulos.
Se o go.work é versionado, normalmente faz sentido avaliar o go.work.sum no mesmo contexto e mantê-lo versionado para reproduzir a resolução. Se o workspace é estritamente pessoal e está no .gitignore, o arquivo de soma correspondente também costuma ser ignorado.
Devo commitar go.work?
Não existe uma resposta única. Use a propriedade do repositório como critério.
Versione o workspace quando
- o repositório é um monorepo deliberado;
- os mesmos módulos devem ser usados juntos por toda a equipe;
- comandos e documentação assumem uma raiz comum;
- o CI testa o conjunto como workspace;
- a lista de módulos é parte da arquitetura do repositório.
Ignore o workspace quando
- cada pessoa combina clones em caminhos diferentes;
- o arquivo serve apenas para testar uma mudança entre repositórios independentes;
- os módulos precisam ser validados prioritariamente como unidades isoladas;
- a lista local inclui forks ou experimentos pessoais;
- o repositório já definiu outra estratégia oficial de build.
Para ignorá-lo:
go.work
go.work.sum
A equipe Go alerta que versionar um go.work pode fazer o CI testar combinações de dependências locais diferentes daquelas que os consumidores realmente recebem. Isso não significa “nunca commite”. Significa que o workspace deve ser uma decisão de repositório, não um arquivo pessoal enviado sem revisão.
Estratégia de CI para múltiplos módulos
Em um monorepo, execute uma camada integrada e uma camada isolada.
1. Teste integrado pelo workspace
Na raiz:
go test ./...
go vet ./...
Isso detecta incompatibilidades entre mudanças locais antes que as versões sejam publicadas.
2. Teste cada módulo com GOWORK=off
Um script simples pode localizar os módulos:
find . -name go.mod -not -path '*/vendor/*' -print0 |
while IFS= read -r -d '' mod; do
dir=$(dirname "$mod")
echo "==> testando $dir"
(
cd "$dir"
GOWORK=off go test ./...
GOWORK=off go vet ./...
)
done
Assim, um módulo não passa no CI apenas porque outro módulo local forneceu uma dependência que ainda não foi publicada ou declarada corretamente.
Para suítes maiores, combine isso com as flags do go test e mantenha -race, cobertura e testes de integração em jobs apropriados.
Padrão prático para mudanças entre repositórios
Workspaces também ajudam fora de monorepos. Suponha dois clones vizinhos:
~/codigo/
├── sdk-pagamentos/
└── checkout-api/
Crie um workspace fora dos repositórios:
mkdir -p ~/codigo/workspaces/checkout
cd ~/codigo/workspaces/checkout
go work init ../../sdk-pagamentos ../../checkout-api
Agora você pode mudar o SDK e testar a API contra o código local. Como o go.work ficou em uma pasta separada, nenhum dos repositórios precisa receber um arquivo temporário.
Antes de abrir os pull requests:
- rode os testes integrados com o workspace;
- rode
GOWORK=off go test ./...em cada módulo; - publique ou faça merge da biblioteca na ordem necessária;
- atualize a versão exigida pela aplicação;
- remova qualquer dependência de uma versão fictícia usada apenas no experimento.
Esse fluxo reduz o intervalo entre “acho que as APIs combinam” e “testei o consumidor real”.
Erros comuns com Go Workspaces
Criar módulos demais
Separar cada pacote em um módulo gera releases, dependências e pipelines sem benefício. Pacotes dentro do mesmo módulo já podem ser importados normalmente. Comece com um módulo e extraia outro quando houver uma fronteira de distribuição real.
Testar somente com o workspace ativo
O código passa localmente, mas falha depois de publicado porque o go.mod exige uma versão antiga. Sempre inclua uma validação com GOWORK=off quando os módulos têm vida independente.
Usar go.work para esconder dependências ausentes
Se o código importa um módulo, o go.mod correspondente deve declarar a dependência adequada. O workspace não é licença para manter metadados incompletos.
Commitar caminhos pessoais
Entradas como /home/joao/fork não funcionam na máquina de outra pessoa. Para workspaces compartilhados, prefira caminhos relativos dentro da estrutura do repositório.
Rodar go work sync sem revisar o diff
A sincronização pode alterar requisitos nos módulos. Trate-a como qualquer comando que edita go.mod: revise, execute go mod tidy onde necessário e valide o build.
Confundir workspace com ferramenta de release
O go.work ajuda a desenvolver módulos em conjunto, mas não define ordem de publicação, tags, changelog ou compatibilidade semântica. O release continua exigindo versões coerentes e dependências publicadas.
Checklist para adotar go.work
- Confirme que existem fronteiras reais entre os módulos.
- Crie o workspace com
go work initego work use. - Verifique o arquivo ativo com
go env GOWORK. - Rode testes integrados na raiz.
- Rode testes isolados com
GOWORK=offem cada módulo. - Decida explicitamente se
go.workego.work.sumentram no Git. - Evite
replacecom caminho local nogo.modpublicado. - Documente o comando padrão de teste para a equipe.
- Revise os diffs depois de
go work sync. - Garanta que releases usem versões reais entre módulos.
Perguntas frequentes
Para que serve o arquivo go.work?
Ele reúne módulos locais em um workspace. Durante o desenvolvimento, imports entre esses módulos apontam para o código local, sem exigir uma versão publicada ou um replace temporário em cada go.mod.
Devo commitar o go.work no Git?
Em um monorepo cujo fluxo oficial depende do workspace, pode fazer sentido. Para combinações pessoais de clones, forks locais ou módulos que devem funcionar isoladamente, normalmente é melhor ignorá-lo. Registre a escolha na documentação do repositório.
Qual é a diferença entre go.work e replace?
go.work configura o ambiente de desenvolvimento que reúne módulos locais. replace altera a resolução declarada dentro de um go.mod. Caminhos locais em replace são fáceis de esquecer e prejudicam a reprodução em outras máquinas.
O go.work substitui o go.mod?
Não. Cada módulo mantém seu próprio go.mod. O workspace apenas coordena quais módulos principais locais participam dos comandos atuais.
Como desativar temporariamente um workspace?
Use GOWORK=off antes do comando:
GOWORK=off go test ./...
Próximos passos
- Go Modules na prática — dependências, versões,
tidye organização do módulo; - Documentação Go em português — como usar
go help,go doce fontes oficiais; - Flags do go test — filtre, repita e diagnostique testes no CI;
- golangci-lint e Staticcheck — mantenha a qualidade entre vários módulos;
- GoReleaser — automatize releases quando módulos produzem CLIs ou binários;
- Vagas de Go no Brasil — acompanhe equipes que trabalham com serviços, plataformas e tooling em Go.
Fontes oficiais
- Tutorial oficial: Getting started with multi-module workspaces
- Referência de módulos: Workspaces
- Documentação do comando go work
Go Workspaces são mais úteis quando permanecem simples: módulos continuam independentes, o workspace acelera o desenvolvimento conjunto e o CI verifica as duas realidades. Se o time entende essa separação, go.work elimina versões provisórias e alterações locais frágeis sem transformar o monorepo em mágica difícil de reproduzir.