Antes dos módulos, Go usava o GOPATH — um diretório global onde todos os projetos e dependências conviviam. Não havia versionamento de dependências, não havia isolamento entre projetos e atualizar uma biblioteca podia quebrar todos os projetos simultaneamente. Era um sistema funcional para projetos pequenos e experimentos, mas inadequado para desenvolvimento profissional em escala.
Go Modules, introduzido como experimental no Go 1.11 e tornado padrão no Go 1.16, resolveu todos esses problemas. Cada projeto tem seu próprio conjunto de dependências versionadas, isolado dos demais. Builds são reproduzíveis — o mesmo código produz o mesmo binário em qualquer máquina. Atualizações são explícitas e controladas.
O arquivo go.mod
O go.mod é o manifesto do módulo. Ele declara o nome do módulo, a versão mínima do Go necessária e todas as dependências diretas:
module github.com/ricardomattos/loja-api
go 1.22
require (
github.com/gin-gonic/gin v1.9.1
github.com/golang-jwt/jwt/v5 v5.2.0
gorm.io/gorm v1.25.7
gorm.io/driver/postgres v1.5.6
)
require (
// dependências indiretas — usadas por dependências diretas
github.com/bytedance/sonic v1.11.3 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
golang.org/x/net v0.22.0 // indirect
)
O caminho do módulo — github.com/ricardomattos/loja-api — é o identificador único do módulo. Por convenção, projetos publicados usam o caminho do repositório onde o código reside. Para projetos privados ou locais, qualquer nome descritivo funciona.
O arquivo go.sum
O go.sum é o guardião da integridade das dependências. Para cada módulo listado no go.mod, o go.sum armazena o hash criptográfico do conteúdo esperado:
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
Quando você ou um colega executa go build ou go test, o Go verifica se os módulos baixados correspondem aos hashes registrados. Se alguém alterar o conteúdo de uma dependência publicada — seja maliciosamente ou por acidente — a verificação falha e o build é recusado.
Nunca edite o go.sum manualmente. Ele é gerenciado automaticamente pelos comandos go. Sempre faça commit de ambos go.mod e go.sum no controle de versão.
Comandos essenciais
Inicializando um módulo:
mkdir loja-api
cd loja-api
go mod init github.com/ricardomattos/loja-api
Adicionando uma dependência:
A forma mais direta é simplesmente importar o pacote no código e executar go mod tidy. Ou adicionar explicitamente com go get:
go get github.com/gin-gonic/gin@v1.9.1
go get gorm.io/gorm@latest
O sufixo @versão aceita: - @v1.9.1 — versão exata - @latest — versão mais recente estável - @main — branch específica (evite em produção) - @v1.9 — prefixo de versão
Removendo dependências não utilizadas e adicionando as faltantes:
go mod tidy
Este é o comando mais usado no dia a dia. Ele analisa todo o código do módulo, remove do go.mod dependências que não são mais importadas, adiciona as que estão sendo importadas mas não declaradas e atualiza o go.sum. Execute go mod tidy antes de todo commit.
Atualizando dependências:
# Atualizar uma dependência específica para a versão mais recente
go get github.com/gin-gonic/gin@latest
# Atualizar todas as dependências diretas para versões patch mais recentes
go get -u=patch ./...
# Atualizar todas as dependências diretas para versões minor mais recentes
go get -u ./...
Verificando dependências:
# Lista todas as dependências e suas versões
go list -m all
# Mostra por que uma dependência está no go.mod
go mod why github.com/gin-gonic/gin
# Verifica se o go.sum está correto
go mod verify
Versionamento semântico
Go Modules adota versionamento semântico — semver — com três componentes: MAJOR.MINOR.PATCH.
- PATCH — correções de bugs sem quebrar compatibilidade:
v1.2.3 → v1.2.4 - MINOR — novas funcionalidades sem quebrar compatibilidade:
v1.2.3 → v1.3.0 - MAJOR — mudanças incompatíveis com versões anteriores:
v1.2.3 → v2.0.0
Go trata versões MAJOR diferentes como módulos completamente distintos. Um módulo na versão v2 ou superior deve ter /v2 no final do caminho do módulo:
github.com/autor/biblioteca ← v0 e v1
github.com/autor/biblioteca/v2 ← v2
github.com/autor/biblioteca/v3 ← v3
Isso permite que um projeto importe v1 e v2 de uma mesma biblioteca simultaneamente sem conflito — cada versão major é tratada como um módulo independente.
Algoritmo de versão mínima (MVS)
O Go usa o Minimum Version Selection para resolver versões de dependências, em vez de "pegar a mais recente". Dado que o projeto A requer B@v1.2 e C@v1.0, e que C@v1.0 requer B@v1.3, o Go seleciona B@v1.3 — a versão mínima que satisfaz todos os requisitos.
Esse algoritmo tem uma propriedade valiosa: ele é determinístico e conservador. Atualizar uma dependência direta nunca atualiza automaticamente outras dependências além do necessário. Isso torna os builds previsíveis e as atualizações controláveis.
Replace e exclude
O go.mod suporta diretivas avançadas para situações especiais.
replace — substitui um módulo por outro, útil para desenvolvimento local ou para usar um fork:
replace (
// Usar versão local durante desenvolvimento
github.com/ricardomattos/pacote-compartilhado => ../pacote-compartilhado
// Usar um fork em vez do original
github.com/original/biblioteca => github.com/meufork/biblioteca v1.0.0-fork
)
Remova todas as diretivas replace de desenvolvimento antes de publicar o módulo — elas não funcionam para quem baixar sua biblioteca.
exclude — exclui uma versão específica de uma dependência, geralmente por conter um bug crítico:
exclude github.com/alguma/biblioteca v1.5.2
Workspaces: múltiplos módulos locais
Go 1.18 introduziu workspaces (go work) para facilitar o desenvolvimento simultâneo de múltiplos módulos relacionados sem precisar usar replace:
# Na raiz que contém os dois módulos
go work init ./loja-api ./pacote-compartilhado
Isso cria um arquivo go.work:
go 1.22
use (
./loja-api
./pacote-compartilhado
)
Com o workspace ativo, mudanças em pacote-compartilhado são imediatamente visíveis em loja-api sem necessidade de publicar ou usar replace. O go.work não deve ser commitado — adicione-o ao .gitignore.
Cache de módulos
Go mantém um cache local de todos os módulos baixados em $GOPATH/pkg/mod. Uma vez baixado, um módulo não é baixado novamente — mesmo em projetos diferentes que usam a mesma versão.
# Ver o diretório do cache
go env GOMODCACHE
# Limpar o cache completamente
go clean -modcache
O cache é somente-leitura após o download, o que evita modificações acidentais. Se precisar editar uma dependência, faça um fork e use replace.
Proxy de módulos
Por padrão, Go baixa módulos através do proxy oficial proxy.golang.org, que serve como cache e espelho de módulos públicos. Isso garante disponibilidade mesmo se o repositório original for removido.
A variável GOPROXY controla quais proxies são usados:
# Padrão — proxy oficial com fallback direto
GOPROXY=https://proxy.golang.org,direct
# Sem proxy — acesso direto aos repositórios
GOPROXY=direct
# Proxy corporativo para ambientes fechados
GOPROXY=https://proxy.minha-empresa.com,direct
A variável GONOSUMCHECK e GONOSUMDB controlam quais módulos ignoram a verificação de integridade — útil para módulos privados que não estão registrados na sumdb pública.
Exemplo completo: projeto real com dependências
mkdir api-tarefas
cd api-tarefas
go mod init github.com/ricardomattos/api-tarefas
// main.go
package main
import (
"github.com/ricardomattos/api-tarefas/internal/handler"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/tarefas", handler.ListarTarefas)
r.POST("/tarefas", handler.CriarTarefa)
r.Run(":8080")
}
# Adicionar dependências detectadas no código
go mod tidy
Após go mod tidy, o go.mod será atualizado automaticamente com Gin e todas as suas dependências transitivas. O go.sum será gerado com os hashes correspondentes.
# Verificar o resultado
cat go.mod
# Confirmar que tudo está correto
go build ./...
go test ./...
Resumo do que foi coberto
Este artigo apresentou Go Modules em profundidade: a estrutura e propósito dos arquivos go.mod e go.sum, os comandos essenciais do dia a dia, versionamento semântico com versões MAJOR como módulos distintos, o algoritmo MVS, as diretivas replace e exclude, workspaces para desenvolvimento multi-módulo, o cache local e o sistema de proxies. Com módulos dominados, o próximo artigo explora a biblioteca padrão do Go.
Referências e leituras complementares
-
Documentação oficial de Go Modules — Referência completa e autoritativa sobre o sistema de módulos. https://go.dev/ref/mod
-
Go Blog: Using Go Modules — Série de artigos introdutórios sobre módulos. https://go.dev/blog/using-go-modules
-
Go Blog: Go Modules in 2019 — Contexto histórico e motivações do sistema de módulos. https://go.dev/blog/modules2019
-
pkg.go.dev — Repositório central de documentação de módulos Go públicos. https://pkg.go.dev
-
Documentação de go work — Referência sobre workspaces para múltiplos módulos. https://go.dev/ref/mod#workspaces
-
Go Proxy Protocol — Especificação do protocolo de proxy de módulos. https://go.dev/ref/mod#goproxy-protocol