Workspace Mode

Workspace Mode para desenvolvimento com múltiplos módulos simultaneamente

O que é 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.

Problema que resolve

Antes do Workspace Mode (Go ≤ 1.17)

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

# 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!

Com Workspace Mode (Go ≥ 1.18)

# 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

Estrutura do arquivo go.work

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

go 1.25

use (
    ./app
    ./library
    ./another-module
)

// Comentários são suportados
replace golang.org/x/net => example.com/fork/net v1.4.5

Diretivas do go.work

Diretiva
Descrição
Exemplo

go

Versão do Go para interpretar o arquivo

go 1.25

use

Módulos ativos no workspace

use ./module-path

replace

Sobrescreve módulos (opcional)

replace foo => bar v1.0.0

toolchain

Especifica toolchain do Go (Go 1.21+)

toolchain go1.25.0

Como funciona?

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

O arquivo go.work é local e não deve ser commitado no repositório. Adicione go.work ao .gitignore.

Criando um Workspace

Método 1: Inicialização com módulos

# 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

Método 2: Adicionar módulos recursivamente

# Adiciona todos os módulos encontrados recursivamente
go work use -r .

# Útil para monorepos com muitos módulos

Exemplo Prático Completo

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

# 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

Modificando a biblioteca

# Adicionar uma nova função em stringutil/reverse.go
cd stringutil

cat >> reverse.go << 'EOF'

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 .

Comandos de Workspace

go work init

Cria um novo arquivo go.work:

# Inicializar vazio
go work init

# Inicializar com módulos
go work init ./module1 ./module2 ./module3

# Inicializar especificando versão do Go
go work init -go=1.25 ./module1

go work use

Adiciona ou remove módulos do workspace:

# 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

go work sync

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

# 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

go work edit

Edita o arquivo go.work:

# 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.25

# Adicionar toolchain
go work edit -toolchain=go1.25.1

go work vendor (Go 1.22+)

Cria um diretório vendor para o workspace inteiro:

# Cria vendor/ com todas as dependências do workspace
go work vendor

# Build usando o vendor
go build -mod=vendor ./...

Variáveis de Ambiente

GOWORK

Controla qual arquivo workspace usar:

# 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

Casos de Uso

1. Desenvolvimento Local de Dependências

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

2. Monorepos

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

3. Contribuindo para Projetos Open Source

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

# 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

Workflow de Release

Quando estiver pronto para publicar:

1. Publicar a biblioteca

cd library
git tag v1.2.0
git push origin v1.2.0

2. Atualizar a aplicação

cd ../app

# Atualizar para usar a versão publicada
go get github.com/user/library@v1.2.0

# Verificar
go mod tidy

3. O workspace continua funcionando

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

Melhores Práticas

✅ Faça

  • Adicione go.work e go.work.sum ao .gitignore

  • 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 faça

  • Nunca comite go.work no repositório (é pessoal)

  • 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

Troubleshooting

Problema: "package X is not in GOROOT or in any module"

# Verifique se todos os módulos estão listados
cat go.work

# Adicione o módulo faltante
go work use ./path/to/module

Problema: Versões de dependências conflitantes

# 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

# 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

go.work.sum

Similar ao go.sum, o arquivo go.work.sum contém checksums das dependências usadas no workspace.

# É criado automaticamente
# Também deve ser adicionado ao .gitignore
echo "go.work" >> .gitignore
echo "go.work.sum" >> .gitignore

Comparação: replace vs workspace

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)

Não (sempre local)

Uso

Override permanente

Desenvolvimento local

Afeta CI

Sim

Não

Recursos Adicionais

Conclusão

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.

Last updated