Pular para o conteúdo

Workspace Mode

Workspace Mode (Modo Workspace) foi introduzido no Go 1.18 (março de 2022) e permite que você trabalhe com múltiplos módulos simultaneamente em um ambiente de desenvolvimento compartilhado.

Imagine que você está desenvolvendo dois módulos: app e library. O app depende de library:

Janela do terminal
# Para testar mudanças locais em library, você precisava:
# 1. Editar app/go.mod adicionando:
replace github.com/user/library => ../library
# 2. Desenvolver e testar
# 3. LEMBRAR de remover a diretiva replace antes de fazer commit
# 4. Publicar library
# 5. Atualizar app para usar a versão publicada

Isso era trabalhoso, especialmente com muitos módulos!

Janela do terminal
# Simplesmente criar um workspace:
go work init ./app ./library
# Agora app automaticamente usa a versão local de library!
# Sem editar go.mod, sem replace, sem problemas

O arquivo go.work tem sintaxe similar ao go.mod:

go 1.27.0
use (
./app
./library
./another-module
)
// Comentários são suportados
replace golang.org/x/net => example.com/fork/net v1.4.5
Diretiva Descrição Exemplo
go Versão mínima do Go para o workspace go 1.27.0
use Módulos ativos no workspace use ./module-path
replace Sobrescreve módulos (opcional) replace foo => bar v1.0.0
toolchain Sugere um toolchain do Go (Go 1.21+) toolchain go1.27.1

Quando um arquivo go.work existe, o comando go:

  1. Trata todos os módulos listados em use como módulos principais
  2. Resolve importações preferindo os módulos do workspace
  3. Permite executar comandos em qualquer módulo a partir da raiz do workspace
  4. Sincroniza dependências entre os módulos quando solicitado
Janela do terminal
# Crie um diretório para o workspace
mkdir meu-workspace
cd meu-workspace
# Inicialize com módulos existentes
go work init ./module1 ./module2
# Ou inicialize vazio e adicione depois
go work init
go work use ./module1
go work use ./module2
Janela do terminal
# Adiciona todos os módulos encontrados recursivamente
go work use -r .
# Útil para monorepos com muitos módulos

Cenário: Desenvolvendo uma aplicação e uma biblioteca juntas

Seção intitulada “Cenário: Desenvolvendo uma aplicação e uma biblioteca juntas”
Janela do terminal
# 1. Criar estrutura do workspace
mkdir projeto
cd projeto
# 2. Criar o módulo da biblioteca
mkdir stringutil
cd stringutil
go mod init github.com/usuario/stringutil
# Criar stringutil/reverse.go
cat > reverse.go << 'EOF'
package stringutil
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)
}
EOF
cd ..
# 3. Criar o módulo da aplicação
mkdir app
cd app
go mod init github.com/usuario/app
# Criar app/main.go
cat > main.go << 'EOF'
package main
import (
"fmt"
"github.com/usuario/stringutil"
)
func main() {
fmt.Println(stringutil.Reverse("Hello, World!"))
}
EOF
cd ..
# 4. Criar o workspace
go work init ./app ./stringutil
# 5. Testar - funciona sem publicar stringutil!
cd app
go run .
# Saída: !dlroW ,olleH
Janela do terminal
# A partir do diretório app, criar outro arquivo na biblioteca
cd ../stringutil
cat > upper.go << 'EOF'
package stringutil
import "strings"
func ToUpper(s string) string {
return strings.ToUpper(s)
}
EOF
# Usar imediatamente em app/main.go sem publicar!
cd ../app
# Modificar main.go para usar ToUpper
# ... app usa a nova função imediatamente
go run .

Cria um novo arquivo go.work:

Janela do terminal
# Inicializar vazio
go work init
# Inicializar com módulos
go work init ./module1 ./module2 ./module3
# Inicializar e depois definir o mínimo do workspace
go work init ./module1
go work edit -go=1.27.1

Adiciona ou remove módulos do workspace:

Janela do terminal
# Adicionar um módulo
go work use ./new-module
# Adicionar múltiplos módulos
go work use ./module1 ./module2
# Adicionar recursivamente todos os módulos
go work use -r .
# Remover um módulo
go work edit -dropuse=./old-module

Sincroniza dependências do workspace para os módulos:

Janela do terminal
# Sincroniza as versões das dependências
go work sync
# Útil quando você quer que todos os módulos usem
# as mesmas versões de dependências comuns

Edita o arquivo go.work:

Janela do terminal
# Adicionar replace
go work edit -replace golang.org/x/net=../my-net
# Remover replace
go work edit -dropreplace golang.org/x/net
# Definir versão do Go
go work edit -go=1.27.1
# Adicionar toolchain
go work edit -toolchain=go1.27.1

Cria um diretório vendor para o workspace inteiro:

Janela do terminal
# Cria vendor/ com todas as dependências do workspace
go work vendor
# Build de todos os módulos usando o vendor (Go 1.25+)
go build -mod=vendor work

Desde Go 1.25, o padrão work inclui os pacotes de todos os módulos do workspace:

Janela do terminal
go build work
go test work

O padrão ./... é relativo ao diretório atual. Se a raiz do workspace não é um módulo, use work ou caminhos como ./app/... ./library/....

No Go 1.27, go work use -r . também ignora diretórios vendor. A linha go do workspace precisa atender à versão mínima de todos os módulos listados em use.

Controla qual arquivo workspace usar:

Janela do terminal
# Usar um arquivo go.work específico
GOWORK=/path/to/custom.work go build
# Desabilitar workspace mode (usar go.mod normalmente)
GOWORK=off go build
# Padrão: Go procura por go.work no diretório atual e pais

Trabalhar em uma aplicação e suas bibliotecas simultaneamente:

workspace/
├── go.work
├── api-server/ # Sua aplicação
│ └── go.mod
├── auth-lib/ # Biblioteca de autenticação
│ └── go.mod
└── database-lib/ # Biblioteca de banco de dados
└── go.mod

Gerenciar múltiplos serviços em um único repositório:

monorepo/
├── go.work
├── user-service/
│ └── go.mod
├── payment-service/
│ └── go.mod
├── notification-service/
│ └── go.mod
└── shared-lib/
└── go.mod

Testar mudanças em um projeto que você está contribuindo:

Janela do terminal
# Clone o projeto que você usa
git clone https://github.com/author/library
# Clone seu fork onde você está fazendo mudanças
git clone https://github.com/you/library library-fork
# Seu projeto
git clone https://github.com/you/app
# Criar workspace
cd app
go work init . ../library-fork
# Agora app usa sua versão modificada de library

Quando estiver pronto para publicar:

Janela do terminal
cd library
git tag v1.2.0
git push origin v1.2.0
Janela do terminal
cd ../app
# Atualizar para usar a versão publicada
go get github.com/user/library@v1.2.0
# Verificar
go mod tidy

Mesmo após publicar, o workspace continua usando a versão local para desenvolvimento contínuo.

  • Adicione go.work e go.work.sum ao .gitignore quando o workspace for pessoal
  • Use workspace para desenvolvimento local
  • Documente no README como configurar o workspace para novos desenvolvedores
  • Use go work sync periodicamente para manter dependências sincronizadas
  • Não versione um workspace pessoal como se fosse a configuração compartilhada do projeto
  • Não confie em workspace para builds de produção
  • Não use replace no go.work se puder evitar (prefira no go.mod se necessário)
  • Não esqueça de testar sem o workspace antes de release

Problema: “package X is not in GOROOT or in any module”

Seção intitulada “Problema: “package X is not in GOROOT or in any module””
Janela do terminal
# Verifique se todos os módulos estão listados
cat go.work
# Adicione o módulo faltante
go work use ./path/to/module
Janela do terminal
# Sincronize as versões
go work sync
# Ou force um módulo específico a atualizar
cd module1
go get dependency@version
cd ..
go work sync

Problema: Build funciona localmente mas falha no CI/CD

Seção intitulada “Problema: Build funciona localmente mas falha no CI/CD”
Janela do terminal
# CI não tem o workspace!
# Certifique-se de que seus go.mod estão corretos:
# Desabilite workspace temporariamente
GOWORK=off go build ./...
# Isso mostrará erros que existem sem o workspace

O go.work.sum registra hashes necessários ao workspace que não aparecem nos arquivos go.sum dos módulos principais. Ele complementa esses arquivos, sem substituí-los.

Janela do terminal
# É criado automaticamente
# Para um workspace pessoal, adicione ao .gitignore
echo "go.work" >> .gitignore
echo "go.work.sum" >> .gitignore
Característica replace (go.mod) workspace (go.work)
Onde Dentro do módulo Fora dos módulos
Escopo Um módulo Múltiplos módulos
Commit Sim (com cuidado) Depende de ser pessoal ou compartilhado
Uso Override permanente Desenvolvimento local
Afeta CI Sim Sim, se estiver presente e habilitado

Workspace Mode é uma ferramenta poderosa para desenvolvimento local com múltiplos módulos. Ele simplifica o workflow, elimina a necessidade de diretivas replace temporárias, e torna o desenvolvimento em monorepos muito mais agradável.