Um módulo é uma árvore de diretórios de pacotes Go com um arquivo go.mod na raiz. O go.mod dá nome ao módulo e lista as versões de todos os outros módulos dos quais ele depende. Você cria um com go mod init:
mkdir myapp
cd myapp
go mod init example.com/myapp
go: creating new go.mod: module example.com/myapp
O go.mod resultante:
module example.com/myapp
go 1.24.5
Isso basta para compilar. Todo projeto Go desde o Go 1.16 é um módulo, e go build, go run . e go test se recusam a funcionar sem um:
go: go.mod file not found in current directory or any parent directory; see 'go help modules'
Escolhendo o caminho do módulo
O caminho do módulo é o prefixo de todo caminho de import dentro do módulo. Com o módulo example.com/myapp, um pacote no diretório internal/store é importado como example.com/myapp/internal/store.
| Situação | Caminho do módulo |
|---|---|
| Código hospedado no GitHub que outros podem importar | github.com/yourname/project |
| Código da sua empresa | yourcompany.com/project ou a URL do repositório |
| Um programa privado ou um exercício | example.com/myapp ou só myapp |
| Versão 2 ou posterior de um módulo publicado | github.com/yourname/project/v2 |
Para uma biblioteca, o caminho precisa bater com o lugar onde o código está, porque o go get o usa para encontrar o repositório. Para um programa que só você executa, o caminho é só um nome. Evite uma palavra única igual a um pacote da biblioteca padrão, como go mod init fmt ou go mod init strings: o build então falha com ambiguous import: found package fmt in multiple modules.
Executar go mod init sem argumento falha fora do antigo layout do GOPATH:
go: cannot determine module path for source directory /home/ana/myapp (outside GOPATH, module path must be specified)
Passe um caminho.
Adicionando dependências
Escreva o import e deixe o Go buscá-lo. Suponha que main.go importa github.com/google/uuid. Compilar antes de o módulo saber dele dá uma instrução clara:
main.go:6:2: no required module provides package github.com/google/uuid; to add it:
go get github.com/google/uuid
Qualquer um dos comandos resolve:
go get github.com/google/uuid
# or, to sync go.mod with every import in the module:
go mod tidy
O go get informa o que mudou:
go: downloading github.com/google/uuid v1.6.0
go: added github.com/google/uuid v1.6.0
O go mod tidy informa como resolveu o import:
go: finding module for package github.com/google/uuid
go: downloading github.com/google/uuid v1.6.0
go: found github.com/google/uuid in github.com/google/uuid v1.6.0
O go.mod agora tem uma linha require:
module example.com/myapp
go 1.24.5
require github.com/google/uuid v1.6.0
go get com versões
| Comando | Efeito |
|---|---|
go get pkg | adiciona pkg na última versão lançada, ou mantém a versão atual se já for requisito |
go get pkg@v1.5.0 | usa exatamente a v1.5.0 (atualiza ou volta a versão) |
go get pkg@latest | passa para a última versão lançada |
go get pkg@abc1234 | usa um commit específico (registrado como pseudo-versão) |
go get -u ./... | atualiza todas as dependências para a última versão minor ou patch |
go get -u=patch ./... | atualiza só para as últimas versões patch |
go get pkg@none | remove o requisito |
go get go@1.24 | eleva a versão mínima do Go do módulo |
O go get altera o go.mod. Ele não compila nem instala mais programas; desde o Go 1.18 isso é trabalho do go install pkg@version.
Dependências indiretas
Requisitos marcados com // indirect são módulos que o seu código não importa diretamente, mas de que o build precisa. Desde o Go 1.17, o go.mod lista todo módulo que fornece um pacote ao build, então as dependências das suas dependências aparecem aqui com essa marca. O go mod tidy gerencia essas marcas; você não as acrescenta.
go mod tidy
Execute go mod tidy sempre que acrescentar ou remover imports. Ele:
- acrescenta requisitos para pacotes importados que estão faltando,
- remove requisitos que nada importa mais,
- acrescenta as entradas de
go.sumde que o build precisa e descarta as antigas.
Ele olha todos os pacotes do módulo, incluindo testes e todas as combinações de build tags, então às vezes mantém uma dependência que você não vê em uso na sua plataforma. Executar go mod tidy antes de cada commit, e verificar no CI que ele não gera diferença, mantém o go.mod honesto.
go.sum
O go.sum registra um hash para cada versão de módulo que o build usa:
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
A primeira linha é o hash dos arquivos do módulo, a segunda só do go.mod dele. Quando o comando go baixa um módulo, ele confere o hash com o go.sum e com o banco de checksums público (sum.golang.org), então uma versão adulterada ou alterada em silêncio falha no build. Commite o go.sum junto com o go.mod, e nunca o edite à mão.
Como o Go escolhe as versões
O Go usa seleção de versão mínima (minimal version selection). Cada módulo lista a versão mínima de cada dependência de que precisa, e o build usa a maior dessas mínimas, nunca algo mais novo. Se o seu módulo exige uuid v1.5.0 e uma dependência exige uuid v1.6.0, o build usa a v1.6.0, mesmo que exista a v1.7.0. Nada é atualizado a menos que alguém peça com go get.
A consequência é que os builds são reproduzíveis sem um arquivo de lock: o go.mod mais o grafo de dependências determinam todas as versões. go list -m all imprime o resultado:
go list -m all
example.com/myapp
github.com/google/uuid v1.6.0
Versões major
Um módulo na v2 ou acima precisa incluir a versão major no caminho: github.com/yourname/project/v2. O caminho de import muda junto, então project e project/v2 são módulos diferentes e podem estar os dois no mesmo build. Essa é a regra do Go para mudanças incompatíveis, e é por isso que você vê imports como github.com/jackc/pgx/v5.
replace: trabalhando em uma dependência localmente
Para testar mudanças em uma dependência antes de publicá-las, aponte o caminho dela para um diretório local:
module example.com/myapp
go 1.24.5
require example.com/mylib v1.2.0
replace example.com/mylib => ../mylib
Ou pela linha de comando:
go mod edit -replace example.com/mylib=../mylib
go mod tidy
O diretório precisa ter o seu próprio go.mod. O replace só vale quando este módulo é compilado diretamente, não quando outra pessoa depende dele, então lembre de removê-lo antes de criar a tag de uma versão.
Para editar vários módulos ao mesmo tempo sem mexer nos go.mod deles, o Go 1.18 trouxe os workspaces:
go work init . ../mylib
Isso grava um arquivo go.work que faz o mylib local ter prioridade. Mantenha o go.work fora do controle de versão, a menos que o time inteiro use o mesmo layout.
Dependências de ferramentas (Go 1.24)
O Go 1.24 trouxe a diretiva tool, para que geradores de código e linters tenham versão no go.mod em vez de serem instalados globalmente:
go get -tool golang.org/x/tools/cmd/stringer
go tool stringer -type=Color
func init é outra coisa
Buscas por "golang init" muitas vezes se referem à função init, que não tem relação com go mod init. Qualquer pacote pode declarar func init(). Ela não recebe argumentos, não pode ser chamada pelo seu código e executa uma vez, automaticamente, depois que as variáveis de nível de pacote são definidas e antes do main:
Um arquivo pode ter várias funções init, e elas executam na ordem em que aparecem. Os pacotes importados terminam a própria inicialização primeiro. Mantenha o init pequeno: trabalho que pode falhar é mais fácil de tratar e testar como uma função comum chamada a partir do main.
Módulos privados e proxies
Por padrão, o go baixa módulos pelo proxy.golang.org. Esse proxy não enxerga repositórios privados, então diga ao Go quais caminhos são privados:
go env -w GOPRIVATE=github.com/yourcompany/*
Módulos que casam com GOPRIVATE são buscados direto no repositório com as suas credenciais do git e pulam o banco de checksums.
Perguntas frequentes
O que o go mod init faz?
Ele cria um arquivo go.mod no diretório atual, o que torna esse diretório a raiz de um módulo. go mod init example.com/myapp grava o caminho do módulo e a versão do Go:
module example.com/myapp
go 1.24.5
Execute uma vez por projeto, antes de go build ou go get.
O que usar como caminho do módulo no go mod init?
O endereço de onde o código será baixado se outras pessoas o importarem, normalmente o caminho do repositório: go mod init github.com/yourname/project. Para um programa que ninguém vai importar, qualquer nome serve (go mod init myapp), mas um caminho com ponto, no estilo de domínio, como example.com/myapp, evita conflito com nomes de pacotes da biblioteca padrão.
Qual a diferença entre go get e go mod tidy?
go get pkg@version adiciona uma dependência ou muda a versão dela. go mod tidy lê os seus arquivos-fonte, acrescenta qualquer módulo de que os seus imports precisam e que falta no go.mod, remove requisitos que nada importa e atualiza o go.sum. Um fluxo comum é escrever o import e depois executar go mod tidy.
Devo commitar o go.sum?
Sim. O go.sum guarda hashes criptográficos de toda versão de módulo que o seu build usa. Commitá-lo permite que o comando go verifique se todo mundo baixa dependências idênticas byte a byte. Nunca o edite à mão; o go mod tidy cuida dele.
"golang init" é o mesmo que go mod init?
Não, são coisas diferentes que compartilham uma palavra. go mod init é um comando de terminal que cria o go.mod. func init() é uma função que você escreve no código Go; ela executa automaticamente uma vez, antes do main, depois que as variáveis do pacote são inicializadas.