Menu

go mod init e moduli Go: go.mod, go get, go mod tidy

Come funzionano i moduli Go: crearne uno con go mod init, scegliere un percorso di modulo, aggiungere dipendenze con go get, fare pulizia con go mod tidy, a cosa serve go.sum e replace per lo sviluppo in locale.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Un modulo è un albero di directory di package Go con un file go.mod nella radice. go.mod dà il nome al modulo ed elenca le versioni di ogni altro modulo da cui dipende. Ne crei uno con go mod init:

mkdir myapp
cd myapp
go mod init example.com/myapp
go: creating new go.mod: module example.com/myapp

Il go.mod risultante:

module example.com/myapp

go 1.24.5

Basta questo per compilare. Da Go 1.16 ogni progetto Go è un modulo, e go build, go run . e go test si rifiutano di funzionare senza:

go: go.mod file not found in current directory or any parent directory; see 'go help modules'

Scegliere un percorso di modulo

Il percorso del modulo è il prefisso di ogni percorso di import all'interno del modulo. Con il modulo example.com/myapp, un package nella directory internal/store si importa come example.com/myapp/internal/store.

SituazionePercorso del modulo
Codice ospitato su GitHub che altri potrebbero importaregithub.com/yourname/project
Codice della tua aziendayourcompany.com/project o l'URL del repository
Un programma privato o un esercizioexample.com/myapp o semplicemente myapp
Versione 2 o successiva di un modulo pubblicatogithub.com/yourname/project/v2

Per una libreria, il percorso deve corrispondere a dove si trova il codice, perché go get lo usa per trovare il repository. Per un programma che esegui solo tu, il percorso è solo un nome. Evita una singola parola che coincide con un package della libreria standard, come go mod init fmt o go mod init strings: in quel caso la build fallisce con ambiguous import: found package fmt in multiple modules.

Eseguire go mod init senza argomenti fallisce al di fuori della vecchia struttura GOPATH:

go: cannot determine module path for source directory /home/ana/myapp (outside GOPATH, module path must be specified)

Passagli un percorso.

Aggiungere dipendenze

Scrivi l'import, poi lascia che Go lo scarichi. Supponi che main.go importi github.com/google/uuid. Compilare prima che il modulo lo conosca produce un'istruzione chiara:

main.go:6:2: no required module provides package github.com/google/uuid; to add it:
	go get github.com/google/uuid

Uno qualsiasi di questi comandi risolve il problema:

go get github.com/google/uuid
# or, to sync go.mod with every import in the module:
go mod tidy

go get riporta cosa ha modificato:

go: downloading github.com/google/uuid v1.6.0
go: added github.com/google/uuid v1.6.0

go mod tidy riporta come ha risolto l'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

Ora go.mod ha una riga require:

module example.com/myapp

go 1.24.5

require github.com/google/uuid v1.6.0

go get con le versioni

ComandoEffetto
go get pkgaggiunge pkg alla sua ultima release, o mantiene la versione attuale se è già richiesto
go get pkg@v1.5.0usa esattamente la v1.5.0 (aggiornamento o downgrade)
go get pkg@latestpassa all'ultima release
go get pkg@abc1234usa un commit specifico (registrato come pseudo-versione)
go get -u ./...aggiorna ogni dipendenza alla sua ultima release minor o patch
go get -u=patch ./...aggiorna solo alle ultime release patch
go get pkg@nonerimuove il requisito
go get go@1.24alza la versione minima di Go del modulo

go get modifica go.mod. Non compila né installa più programmi; da Go 1.18 quello è il compito di go install pkg@version.

Dipendenze indirette

I requisiti marcati // indirect sono moduli che il tuo codice non importa direttamente ma che servono alla build. Da Go 1.17, go.mod elenca ogni modulo che fornisce un package alla build, quindi le dipendenze delle tue dipendenze compaiono qui con quel marcatore. go mod tidy gestisce questi marcatori; non li aggiungi tu.

go mod tidy

Esegui go mod tidy ogni volta che aggiungi o rimuovi degli import. Il comando:

  • aggiunge i requisiti mancanti per i package importati,
  • rimuove i requisiti che nessuno importa più,
  • aggiunge le voci di go.sum necessarie alla build ed elimina quelle obsolete.

Esamina ogni package del modulo, compresi i test e tutte le combinazioni di build tag, quindi a volte mantiene una dipendenza che sulla tua piattaforma non vedi usata. Eseguire go mod tidy prima di ogni commit, e controllare in CI che non produca differenze, mantiene go.mod affidabile.

go.sum

go.sum registra un hash per ogni versione di modulo usata dalla build:

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=

La prima riga contiene l'hash dei file del modulo, la seconda solo quello del suo go.mod. Quando il comando go scarica un modulo, confronta l'hash con go.sum e con il database pubblico dei checksum (sum.golang.org), quindi una release manomessa o modificata di nascosto fa fallire la build. Fai il commit di go.sum insieme a go.mod e non modificarlo mai a mano.

Come Go sceglie le versioni

Go usa la selezione della versione minima. Ogni modulo elenca la versione minima di ogni dipendenza di cui ha bisogno, e la build usa la più alta di queste versioni minime, mai qualcosa di più recente. Se il tuo modulo richiede uuid v1.5.0 e una dipendenza richiede uuid v1.6.0, la build usa la v1.6.0, anche se esiste la v1.7.0. Niente viene aggiornato a meno che qualcuno non lo chieda con go get.

La conseguenza è che le build sono riproducibili senza un file di lock: go.mod più il grafo delle dipendenze determina completamente ogni versione. go list -m all stampa il risultato:

go list -m all
example.com/myapp
github.com/google/uuid v1.6.0

Versioni major

Un modulo alla v2 o successiva deve includere la versione major nel suo percorso: github.com/yourname/project/v2. Il percorso di import cambia di conseguenza, quindi project e project/v2 sono moduli diversi e possono stare entrambi nella stessa build. È la regola di Go per le modifiche incompatibili, ed è per questo che vedi import come github.com/jackc/pgx/v5.

replace: lavorare su una dipendenza in locale

Per provare le modifiche a una dipendenza prima di pubblicarle, fai puntare il suo percorso a una directory locale:

module example.com/myapp

go 1.24.5

require example.com/mylib v1.2.0

replace example.com/mylib => ../mylib

Oppure dalla riga di comando:

go mod edit -replace example.com/mylib=../mylib
go mod tidy

La directory deve contenere il proprio go.mod. replace si applica solo quando compili direttamente questo modulo, non quando qualcun altro dipende da esso, quindi ricordati di rimuoverlo prima di taggare una release.

Per modificare più moduli contemporaneamente senza toccare i loro file go.mod, Go 1.18 ha aggiunto i workspace:

go work init . ../mylib

Questo scrive un file go.work che dà la precedenza al mylib locale. Tieni go.work fuori dal controllo di versione, a meno che tutto il team non usi la stessa struttura.

Dipendenze degli strumenti (Go 1.24)

Go 1.24 ha aggiunto una direttiva tool, così generatori di codice e linter possono avere la loro versione registrata in go.mod invece di essere installati globalmente:

go get -tool golang.org/x/tools/cmd/stringer
go tool stringer -type=Color

func init è un'altra cosa

Chi cerca "golang init" spesso intende la funzione init, che non ha niente a che fare con go mod init. Qualsiasi package può dichiarare func init(). Non riceve argomenti, non può essere chiamata dal tuo codice e viene eseguita una volta, automaticamente, dopo che le variabili a livello di package sono state impostate e prima di main:

Un file può avere più funzioni init, che vengono eseguite nell'ordine in cui compaiono. I package importati completano prima la propria inizializzazione. Tieni init piccola: il lavoro che può fallire è più facile da gestire e testare come normale funzione chiamata da main.

Moduli privati e proxy

Per impostazione predefinita go scarica i moduli tramite proxy.golang.org. Quel proxy non può vedere i repository privati, quindi indica a Go quali percorsi sono privati:

go env -w GOPRIVATE=github.com/yourcompany/*

I moduli che corrispondono a GOPRIVATE vengono scaricati direttamente dal repository con le tue credenziali git e saltano il database dei checksum.

Domande frequenti

Cosa fa go mod init?

Crea un file go.mod nella directory corrente, che diventa così la radice di un modulo. go mod init example.com/myapp scrive il percorso del modulo e la versione di Go:

module example.com/myapp

go 1.24.5

Eseguilo una volta per progetto, prima di go build o go get.

Cosa devo usare come percorso del modulo in go mod init?

L'indirizzo da cui verrà scaricato il codice se altri lo importano, di solito il percorso del repository: go mod init github.com/yourname/project. Per un programma che nessuno importerà va bene qualsiasi nome (go mod init myapp), ma un percorso in stile dominio con un punto, come example.com/myapp, evita conflitti con i nomi dei package della libreria standard.

Qual è la differenza tra go get e go mod tidy?

go get pkg@version aggiunge una dipendenza o ne cambia la versione. go mod tidy legge i tuoi file sorgente, aggiunge ogni modulo richiesto dai tuoi import ma assente da go.mod, rimuove i requisiti che nessuno importa e aggiorna go.sum. Un flusso comune è scrivere l'import e poi eseguire go mod tidy.

Devo fare il commit di go.sum?

Sì. go.sum contiene gli hash crittografici di ogni versione di modulo usata dalla tua build. Farne il commit permette al comando go di verificare che tutti scarichino dipendenze identiche byte per byte. Non modificarlo mai a mano; lo gestisce go mod tidy.

"golang init" è la stessa cosa di go mod init?

No, sono due cose diverse che condividono una parola. go mod init è un comando da terminale che crea go.mod. func init() è una funzione che scrivi nel codice Go; viene eseguita automaticamente una volta, prima di main, dopo che le variabili del package sono state inizializzate.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA