ProgrammazioneSviluppatore Go

Come funziona go modules e la gestione delle dipendenze in Go? Quali problemi possono sorgere durante l'aggiornamento o il fissaggio delle dipendenze?

Supera i colloqui con l'assistente IA Hintsage

Risposta

Go Modules è il meccanismo standard di gestione delle dipendenze introdotto in Go 1.11+. I file principali sono go.mod (definisce le dipendenze minime e le loro versioni) e go.sum (garantisce l'integrità attraverso gli hash).

Per aggiungere una dipendenza si utilizza:

go get github.com/pkg/errors@v0.9.1

Per aggiornare le dipendenze —

go get -u ./... go mod tidy # rimuovere non utilizzato

Go supporta la versioning semantico (semver) e le dipendenze sono fissate in modo rigido: il progetto è ripetibile, la build è deterministica. Ma è importante considerare:

  • L'uso di percorsi replace (<replace github.com/pkg/errors = ../errors>) comporta rischi di incompatibilità.
  • Un errore nella modifica manuale di go.mod può portare a incompatibilità di versioni, conflitti di dipendenze transitive.
  • Alcune dipendenze utilizzano un altro sistema (dep, vendoring), il che provoca complicazioni nella migrazione.

Domanda trabocchetto

Cosa succede se si elimina il file go.sum e si esegue il comando go build, e perché è pericoloso?

Molti pensano che Go ricostruirà semplicemente le dipendenze da zero. Ma il file go.sum contiene gli hash di tutti i moduli utilizzati e protegge dalle sostituzioni (supply-chain attack). Se viene rimosso, alla successiva build Go scaricherà nuovamente le dipendenze, ricreerà il file, ma se il repository della dipendenza è stato modifica da un malintenzionato — la protezione è rotta! È possibile una sostituzione del codice in produzione.

Esempi di errori reali a causa della mancanza di conoscenza delle sottigliezze della tematica


Storia

In un grande progetto, il repository è passato da vendoring a go modules, sono stati dimenticati di fissare le versioni. Dopo un mese gli aggiornamenti dei pacchetti di terze parti hanno rotto la compatibilità, è diventato impossibile compilare il vecchio ramo — il codice ha perso ripetibilità.


Storia

In un altro progetto, uno sviluppatore ha accidentalmente eliminato go.sum. Dopo un nuovo tentativo, il team ha notato che alcune dipendenze erano cambiate, sono emersi bug legati all'incompatibilità delle versioni minor — per questo c'è stato un rollback di diversi giorni fa.


Storia

L'uso di percorsi replace su directory locali (replace ... = ../some/library) non è stato rimosso prima del deployment — nel pipeline CI/CD la build è fallita, poiché il sistema esterno non aveva accesso ai file locali, e la produzione è stata "pinnata" a una versione errata.