Lezioni del modulo (4/5)
Go modules
Un modulo Go è un'unità versionabile composta da uno o più package. È la base del sistema di dipendenze moderno (Go 1.11+): niente più GOPATH, niente più vendor obbligatorio, dipendenze esplicite e riproducibili.
go.mod: il manifest del modulo
module example.com/myapp
go 1.22
require (
github.com/google/uuid v1.6.0
golang.org/x/time v0.5.0
)
Tre direttive principali:
module <path>— il path d'importazione del modulo. Tutti i package interni si importano comeexample.com/myapp/sub/pkg. Non è obbligato essere un URL reale, ma per pubblicare sugo getdeve risolvere.go <version>— la versione minima di Go richiesta (anche per controllare quali feature del linguaggio sono ammesse, es. range-over-func in 1.23).require— le dipendenze dirette con versione precisa.
Altre direttive: replace (sostituisce una dep con una fork o un path locale), exclude, retract.
go.sum: il lockfile crittografico
Affiancato a go.mod, go.sum contiene un hash crittografico di OGNI versione scaricata (incluse le dep transitive). Garantisce riproducibilità: se qualcuno tampera una versione pubblicata, il build fallisce.
Va sempre committato. Va aggiornato automaticamente dai comandi go.
Comandi essenziali
go mod init example.com/myapp # crea go.mod
go get github.com/google/uuid # aggiunge dep all'ultima versione
go get github.com/google/uuid@v1.5.0 # versione specifica
go get -u ./... # upgrade di tutte le dep
go mod tidy # rimuove deps non usate, aggiunge mancanti
go mod download # scarica tutto in cache
go mod why github.com/x/y # spiega perché una dep è inclusa
go mod graph # grafo completo delle dipendenzego mod tidy è quello che invochi dopo ogni modifica agli import: garantisce che go.mod rifletta esattamente i package effettivamente usati.
Semantic Import Versioning (SIV)
Le versioni seguono SemVer: v1.2.3 = MAJOR.MINOR.PATCH. La parte interessante è la major v2+:
- Major
v0ev1→ path normale:github.com/foo/bar. - Major
v2o successive → il path include la versione major:github.com/foo/bar/v2.
import "github.com/foo/bar/v2"Questo permette di importare contemporaneamente v1 e v2 di una stessa libreria (utile durante migrazioni progressive).
Path d'import e package interni
Se il tuo modulo è example.com/myapp, una sub-cartella utils/ viene importata come:
import "example.com/myapp/utils"Il path dipende solo dal nome dichiarato in go.mod, non dalla posizione su disco: lo stesso codice in cartelle diverse continua a funzionare.
Workspace mode (Go 1.18+)
Per lavorare contemporaneamente su più moduli che si referenziano (es. una libreria e un'app che la usa):
go work init ./lib ./appCrea go.work: go build userà la versione locale di ./lib invece di scaricare quella pubblicata. Non committare go.work (è ambiente di sviluppo).
Esercizi
Il modulo è example.com/myapp e contiene una sub-cartella utils. Importa il sub-package nel main usando il path completo.
Mostra suggerimento
L'import path è il nome del modulo (da go.mod) + il path relativo della cartella.
Soluzione disponibile dopo 3 tentativi
Trasforma i singoli import in un import group con la sintassi import ( ... ), importando sia fmt che os.
Soluzione disponibile dopo 3 tentativi
Quale comando rimuove dal go.mod le dipendenze non più importate e aggiunge quelle mancanti?
$ go mod ???