ProgrammatieGo ontwikkelaar

Hoe werken go modules en afhankelijkheidsbeheer in Go? Welke valkuilen kunnen zich voordoen bij het updaten of vastleggen van afhankelijkheden?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

Go Modules is het standaard mechanisme voor afhankelijkheidsbeheer, geïntroduceerd in Go 1.11+. De belangrijkste bestanden zijn go.mod (bepaalt minimale afhankelijkheden en hun versies) en go.sum (garandeert integriteit via hashes).

Voor het toevoegen van een afhankelijkheid wordt het volgende gebruikt:

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

Voor het updaten van afhankelijkheden —

go get -u ./... go mod tidy # verwijder ongebruikte

Go ondersteunt semantische versionering (semver), en afhankelijkheden worden strikt vastgelegd: het project is reproduceerbaar, de build is deterministisch. Maar houd rekening met:

  • Bij gebruik van replace-paden (<replace github.com/pkg/errors = ../errors>) bestaat het risico van incompatibiliteit.
  • Een fout bij handmatig corrigeren van go.mod kan leiden tot incompatibiliteit van versies, conflicten tussen transitieve afhankelijkheden.
  • Sommige afhankelijkheden gebruiken een ander systeem (dep, vendoring), wat migratie bemoeilijkt.

Misleidende vraag

Wat gebeurt er als het bestand go.sum wordt verwijderd en de opdracht go build wordt uitgevoerd, en waarom is dit gevaarlijk?

Veel mensen denken dat Go gewoon de afhankelijkheden vanaf nul opnieuw zal bouwen. Maar het bestand go.sum bevat hashes van alle gebruikte modules en beschermt tegen vervangingen (supply-chain-aanval). Als het wordt verwijderd, bij de volgende build zal Go de afhankelijkheden opnieuw downloaden, het bestand opnieuw aanmaken, maar als de afhankelijkheid repository door een aanvaller is gewijzigd — is de bescherming doorbroken! Code vervangingen in productie zijn mogelijk.

Voorbeelden van echte fouten door onbekendheid met de details van het onderwerp


Verhaal

In een groot project is de repository overgestapt van vendoring naar go modules, en ze vergaten de versies vast te leggen. Een maand later veroorzaakten updates van externe pakketten incompatibiliteit, het werd onmogelijk om de oude tak te bouwen — de code verloor reproduceerbaarheid.


Verhaal

In een ander project verwijderde een ontwikkelaar per ongeluk go.sum. Na een herstart merkte het team dat een deel van de afhankelijkheden was veranderd, er verschenen bugs gerelateerd aan de incompatibiliteit van minor-versies — hierdoor ontstond een terugrol van enkele dagen terug.


Verhaal

Het gebruik van replace-paden naar lokale directories (replace ... = ../some/library) was niet verwijderd voor de deployment — in de CI/CD-pijplijn faalde de build, omdat het externe systeem geen toegang had tot lokale bestanden, en de productie bleek "vastgezet" op een onjuiste versie.