O que é Module em Go?

Um module (módulo) é a unidade de distribuição e versionamento de código em Go. Introduzido no Go 1.11 e tornado padrão a partir do Go 1.16, o sistema de módulos resolve o gerenciamento de dependências de forma nativa, sem precisar de ferramentas externas como o antigo dep ou govendor. Todo projeto Go moderno é organizado como um módulo, definido por um arquivo go.mod na raiz do projeto.

Na prática, quando você cria um novo projeto Go — seja uma API REST, uma ferramenta de CLI ou uma biblioteca compartilhada — o primeiro passo é inicializar um módulo. O módulo define o caminho de importação do seu código, lista suas dependências e garante builds reproduzíveis através do arquivo go.sum.

Antes dos módulos, Go usava o GOPATH como workspace único para todo código Go, o que tornava impossível ter versões diferentes de uma mesma dependência em projetos distintos. O sistema de módulos resolveu esse problema de forma elegante, permitindo que cada projeto tenha suas próprias dependências isoladas com versões específicas.

Estrutura do go.mod

O arquivo go.mod é o coração de qualquer módulo Go. Ele contém quatro tipos de diretivas:

module github.com/meuusuario/meuprojeto

go 1.22

require (
    github.com/gin-gonic/gin v1.9.1
    github.com/lib/pq v1.10.9
    golang.org/x/sync v0.6.0
)

require (
    // Dependências indiretas (transitivas)
    github.com/bytedance/sonic v1.11.2 // indirect
    golang.org/x/net v0.21.0 // indirect
)

Diretivas principais

  • module: define o caminho de importação do módulo — geralmente corresponde ao URL do repositório
  • go: versão mínima de Go necessária para compilar o projeto
  • require: lista de dependências com suas versões exatas
  • indirect: dependências que não são importadas diretamente pelo seu código, mas são necessárias para as dependências diretas

Inicializando um módulo

Para criar um novo módulo Go:

# Criar diretório do projeto
mkdir meuprojeto && cd meuprojeto

# Inicializar o módulo
go mod init github.com/meuusuario/meuprojeto

O caminho do módulo segue convenções importantes:

# Projeto público no GitHub
go mod init github.com/usuario/projeto

# Projeto em Gitea privado
go mod init git.empresa.com/equipe/projeto

# Módulo da biblioteca padrão
go mod init golang.org/x/tools

Após inicializar, qualquer código Go dentro do diretório (e subdiretórios) pode ser importado usando o caminho do módulo como prefixo. Os packages dentro do módulo são organizados por diretórios.

Comandos essenciais

go mod tidy

O comando mais usado no dia a dia — sincroniza o go.mod com o código real:

go mod tidy

Ele adiciona dependências que estão no código mas faltam no go.mod, e remove dependências listadas no go.mod que não são mais usadas. Execute sempre antes de fazer commit para manter o go.mod limpo e preciso.

go get

Adiciona ou atualiza dependências:

# Adicionar uma dependência
go get github.com/gorilla/mux

# Atualizar para versão específica
go get github.com/gorilla/mux@v1.8.1

# Atualizar para última versão
go get -u github.com/gorilla/mux

# Atualizar todas as dependências
go get -u ./...

# Remover uma dependência
go get github.com/gorilla/mux@none

go mod vendor

Copia todas as dependências para um diretório vendor/ local:

go mod vendor

O vendoring é útil para builds offline, auditorias de segurança e ambientes CI/CD onde você quer garantir que as dependências estejam disponíveis sem acesso à internet. Muitas empresas que trabalham com microsserviços em Go adotam vendoring como prática padrão.

go mod graph e go mod why

# Mostrar grafo de dependências
go mod graph

# Explicar por que uma dependência existe
go mod why golang.org/x/net

O arquivo go.sum

O go.sum contém hashes criptográficos de cada dependência baixada:

github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqFPSA=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL/0KcuqOY...=

Esse arquivo garante integridade e reprodutibilidade: se alguém tentar alterar o código de uma dependência, o hash não vai bater e o build falhará. Nunca adicione go.sum ao .gitignore — ele deve ser versionado junto com go.mod.

O Go também utiliza o checksum database em sum.golang.org para verificar hashes contra um registro público, prevenindo ataques de supply chain.

Versionamento semântico (SemVer)

Go adota versionamento semântico estrito:

v1.2.3
│ │ │
│ │ └── Patch: correções de bugs (backward-compatible)
│ └──── Minor: novas features (backward-compatible)
└────── Major: breaking changes (incompatível)

A regra do Major version

A partir da versão v2, o caminho do módulo deve incluir o sufixo de versão:

// go.mod para v1
module github.com/meuusuario/meuprojeto

// go.mod para v2
module github.com/meuusuario/meuprojeto/v2

Isso permite que um projeto importe v1 e v2 da mesma dependência simultaneamente, facilitando migrações graduais — algo especialmente útil em projetos grandes.

Diretiva replace

A diretiva replace redireciona importações para outro caminho ou versão:

module meuprojeto

go 1.22

require github.com/meulib/core v1.5.0

// Redirecionar para fork local durante desenvolvimento
replace github.com/meulib/core => ../meulib-core

// Redirecionar para um fork no GitHub
replace github.com/meulib/core => github.com/meufork/core v1.5.1

Casos de uso comuns para replace:

  • Desenvolvimento local: apontar para uma cópia local de uma biblioteca enquanto faz alterações
  • Forks: usar seu fork em vez da biblioteca original
  • Correções urgentes: aplicar patches antes de um release oficial
  • Módulos privados: redirecionar para repositórios internos

Lembre-se: replace no go.mod de uma biblioteca é ignorado por quem importa essa biblioteca. Apenas o go.mod do módulo principal (o executável) tem seus replace respeitados.

Workspace mode (go.work)

Introduzido no Go 1.18, o workspace mode permite trabalhar com múltiplos módulos simultaneamente:

# Criar workspace
go work init ./meuprojeto ./minhalib

# Arquivo go.work criado
// go.work
go 1.22

use (
    ./meuprojeto
    ./minhalib
)

O workspace substitui múltiplas diretivas replace quando você desenvolve vários módulos relacionados localmente. É perfeito para monorepos e projetos onde você está editando uma biblioteca e um consumidor ao mesmo tempo.

# Adicionar módulo ao workspace
go work use ./outro-modulo

# Sincronizar workspace
go work sync

Módulos privados

Para módulos hospedados em repositórios privados (como Gitea ou GitLab corporativo):

# Configurar GOPRIVATE para pular o proxy público
export GOPRIVATE=git.empresa.com/*

# Ou configurar globalmente
go env -w GOPRIVATE="git.empresa.com/*,github.com/minha-org/*"

O GOPRIVATE instrui o Go a baixar diretamente do repositório em vez de usar o proxy público (proxy.golang.org), evitando que código privado seja exposto.

Variáveis de ambiente relacionadas

  • GOPRIVATE: módulos que não devem usar proxy nem checksum database
  • GONOSUMCHECK: módulos que não devem ser verificados contra sum.golang.org
  • GONOSUMDB: módulos que não devem ser consultados no sum database
  • GOPROXY: URL do proxy de módulos (padrão: proxy.golang.org)

Boas práticas com módulos Go

  1. Execute go mod tidy antes de cada commit — mantém dependências limpas
  2. Versione go.mod e go.sum — ambos devem estar no controle de versão
  3. Use versões exatas em produção — evite go get -u sem análise de impacto
  4. Configure GOPRIVATE para módulos internos — evita vazamento de código
  5. Prefira bibliotecas com releases tagados — garante estabilidade
  6. Revise dependências transitivas — use go mod graph para entender o que você está importando

Para aprender mais sobre organização de código Go, explore o glossário de packages e os tutoriais de Go para iniciantes. Para entender como módulos se integram com Docker e CI/CD, confira nossos tutoriais especializados.

Perguntas frequentes (FAQ)

Qual a diferença entre module e package em Go?

Um package é um diretório de arquivos Go que compartilham o mesmo namespace, enquanto um module é uma coleção de packages relacionados versionados juntos. O module é definido pelo go.mod na raiz e pode conter múltiplos packages organizados em subdiretórios. Pense no module como o projeto inteiro e packages como as pastas dentro dele.

Preciso fazer commit do go.sum?

Sim, sempre. O go.sum garante que todos os desenvolvedores e o CI/CD usem exatamente as mesmas versões de dependências com os mesmos hashes criptográficos. Sem ele, builds podem usar código diferente em máquinas diferentes, causando bugs difíceis de reproduzir.

Como resolver conflitos de dependência em Go?

Use go mod tidy para limpar e go mod graph para visualizar o grafo de dependências. Se duas dependências requerem versões incompatíveis de uma terceira, Go aplica Minimum Version Selection (MVS) — seleciona a menor versão que satisfaz todos os requisitos. Em casos extremos, use replace para forçar uma versão específica.

Quando usar go mod vendor?

Use vendoring quando precisar de builds offline, auditorias de segurança corporativa ou controle total sobre as dependências no repositório. Em ambientes de CI/CD onde o acesso a registros externos pode ser instável, vendoring garante builds consistentes. Para projetos open source, vendoring geralmente não é necessário.