Un module est une arborescence de packages Go avec un fichier go.mod à sa racine. go.mod nomme le module et liste les versions de tous les autres modules dont il dépend. Vous en créez un avec go mod init :
mkdir myapp
cd myapp
go mod init example.com/myapp
go: creating new go.mod: module example.com/myapp
Le go.mod obtenu :
module example.com/myapp
go 1.24.5
Cela suffit pour compiler. Tout projet Go depuis Go 1.16 est un module, et go build, go run . et go test refusent de fonctionner sans :
go: go.mod file not found in current directory or any parent directory; see 'go help modules'
Choisir un chemin de module
Le chemin du module est le préfixe de chaque chemin d'import à l'intérieur du module. Avec le module example.com/myapp, un package du répertoire internal/store s'importe comme example.com/myapp/internal/store.
| Situation | Chemin de module |
|---|---|
| Code hébergé sur GitHub que d'autres peuvent importer | github.com/yourname/project |
| Le code de votre entreprise | yourcompany.com/project ou l'URL du dépôt |
| Un programme privé ou un exercice | example.com/myapp ou simplement myapp |
| Version 2 ou plus d'un module publié | github.com/yourname/project/v2 |
Pour une bibliothèque, le chemin doit correspondre à l'endroit où vit le code, car go get s'en sert pour trouver le dépôt. Pour un programme que vous seul exécutez, le chemin n'est qu'un nom. Évitez un mot unique qui correspond à un package de la bibliothèque standard, comme go mod init fmt ou go mod init strings : le build échoue alors avec ambiguous import: found package fmt in multiple modules.
Lancer go mod init sans argument échoue en dehors de l'ancienne organisation GOPATH :
go: cannot determine module path for source directory /home/ana/myapp (outside GOPATH, module path must be specified)
Donnez-lui un chemin.
Ajouter des dépendances
Écrivez l'import, puis laissez Go le récupérer. Supposons que main.go importe github.com/google/uuid. Compiler avant que le module le connaisse donne une instruction claire :
main.go:6:2: no required module provides package github.com/google/uuid; to add it:
go get github.com/google/uuid
L'une ou l'autre commande règle le problème :
go get github.com/google/uuid
# or, to sync go.mod with every import in the module:
go mod tidy
go get indique ce qu'il a changé :
go: downloading github.com/google/uuid v1.6.0
go: added github.com/google/uuid v1.6.0
go mod tidy indique comment il a résolu 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
go.mod contient maintenant une ligne require :
module example.com/myapp
go 1.24.5
require github.com/google/uuid v1.6.0
go get avec des versions
| Commande | Effet |
|---|---|
go get pkg | ajoute pkg à sa dernière version publiée, ou garde la version actuelle s'il est déjà requis |
go get pkg@v1.5.0 | utilise exactement v1.5.0 (montée ou descente de version) |
go get pkg@latest | passe à la dernière version publiée |
go get pkg@abc1234 | utilise un commit précis (enregistré comme pseudo-version) |
go get -u ./... | met chaque dépendance à jour vers sa dernière version mineure ou corrective |
go get -u=patch ./... | met à jour vers les dernières versions correctives uniquement |
go get pkg@none | retire l'exigence |
go get go@1.24 | relève la version minimale de Go du module |
go get modifie go.mod. Il ne compile ni n'installe plus de programmes ; depuis Go 1.18, c'est le rôle de go install pkg@version.
Dépendances indirectes
Les exigences marquées // indirect sont des modules que votre code n'importe pas directement mais dont le build a besoin. Depuis Go 1.17, go.mod liste chaque module qui fournit un package au build, donc les dépendances de vos dépendances apparaissent ici avec ce marqueur. go mod tidy gère ces marqueurs ; vous ne les ajoutez pas vous-même.
go mod tidy
Lancez go mod tidy chaque fois que vous ajoutez ou retirez des imports. Il :
- ajoute les exigences manquantes pour les packages importés,
- retire les exigences que plus rien n'importe,
- ajoute les entrées
go.sumdont le build a besoin et supprime celles qui sont périmées.
Il examine tous les packages du module, y compris les tests et toutes les combinaisons de build tags, donc il garde parfois une dépendance que vous ne voyez pas utilisée sur votre plateforme. Lancer go mod tidy avant chaque commit, et vérifier en CI qu'il ne produit aucune différence, garde go.mod honnête.
go.sum
go.sum enregistre une empreinte pour chaque version de module utilisée par le 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 première ligne hache les fichiers du module, la seconde uniquement son go.mod. Quand la commande go télécharge un module, elle compare l'empreinte à go.sum et à la base de sommes de contrôle publique (sum.golang.org), donc une version altérée ou modifiée en douce fait échouer le build. Committez go.sum à côté de go.mod, et ne le modifiez jamais à la main.
Comment Go choisit les versions
Go utilise la sélection de version minimale. Chaque module liste la version minimale de chaque dépendance dont il a besoin, et le build utilise la plus haute de ces versions minimales, jamais une plus récente. Si votre module exige uuid v1.5.0 et qu'une dépendance exige uuid v1.6.0, le build utilise v1.6.0, même si v1.7.0 existe. Rien n'est mis à jour tant que personne ne le demande avec go get.
La conséquence : les builds sont reproductibles sans fichier de verrouillage. go.mod plus le graphe des dépendances détermine entièrement chaque version. go list -m all affiche le résultat :
go list -m all
example.com/myapp
github.com/google/uuid v1.6.0
Versions majeures
Un module en v2 ou plus doit inclure la version majeure dans son chemin : github.com/yourname/project/v2. Le chemin d'import change avec, donc project et project/v2 sont des modules différents et peuvent coexister dans un même build. C'est la règle de Go pour les changements incompatibles, et c'est pourquoi vous voyez des imports comme github.com/jackc/pgx/v5.
replace : travailler sur une dépendance en local
Pour tester des modifications d'une dépendance avant de les publier, faites pointer son chemin vers un répertoire local :
module example.com/myapp
go 1.24.5
require example.com/mylib v1.2.0
replace example.com/mylib => ../mylib
Ou en ligne de commande :
go mod edit -replace example.com/mylib=../mylib
go mod tidy
Le répertoire doit contenir son propre go.mod. replace ne s'applique que lorsqu'on compile ce module directement, pas quand quelqu'un d'autre en dépend, alors pensez à le retirer avant de publier une version.
Pour modifier plusieurs modules à la fois sans toucher à leurs fichiers go.mod, Go 1.18 a ajouté les workspaces :
go work init . ../mylib
Cela écrit un fichier go.work qui donne la priorité au mylib local. Gardez go.work hors du contrôle de version, sauf si toute l'équipe utilise la même organisation.
Dépendances d'outils (Go 1.24)
Go 1.24 a ajouté une directive tool, pour que les générateurs de code et les linters soient versionnés dans go.mod au lieu d'être installés globalement :
go get -tool golang.org/x/tools/cmd/stringer
go tool stringer -type=Color
func init, c'est autre chose
Les recherches « golang init » visent souvent la fonction init, qui n'a rien à voir avec go mod init. N'importe quel package peut déclarer func init(). Elle ne prend pas d'argument, ne peut pas être appelée par votre code, et s'exécute une fois, automatiquement, après l'initialisation des variables du package et avant main :
Un fichier peut avoir plusieurs fonctions init, et elles s'exécutent dans leur ordre d'apparition. Les packages importés terminent d'abord leur propre initialisation. Gardez init court : un travail qui peut échouer est plus facile à gérer et à tester sous forme de fonction ordinaire appelée depuis main.
Modules privés et proxys
Par défaut, go télécharge les modules via proxy.golang.org. Ce proxy ne voit pas les dépôts privés, donc indiquez à Go quels chemins sont privés :
go env -w GOPRIVATE=github.com/yourcompany/*
Les modules qui correspondent à GOPRIVATE sont récupérés directement depuis le dépôt avec vos identifiants git et ne passent pas par la base de sommes de contrôle.
Questions fréquentes
Que fait go mod init ?
Il crée un fichier go.mod dans le répertoire courant, ce qui fait de ce répertoire la racine d'un module. go mod init example.com/myapp écrit le chemin du module et la version de Go :
module example.com/myapp
go 1.24.5
Lancez-le une fois par projet, avant go build ou go get.
Quel chemin de module utiliser avec go mod init ?
L'adresse d'où le code sera récupéré si d'autres l'importent, généralement le chemin du dépôt : go mod init github.com/yourname/project. Pour un programme que personne n'importera, n'importe quel nom convient (go mod init myapp), mais un chemin de type domaine avec un point, comme example.com/myapp, évite les conflits avec les noms de packages de la bibliothèque standard.
Quelle est la différence entre go get et go mod tidy ?
go get pkg@version ajoute une dépendance ou change sa version. go mod tidy lit vos fichiers source, ajoute tout module dont vos imports ont besoin et qui manque dans go.mod, retire les exigences que rien n'importe, et met à jour go.sum. Un enchaînement courant consiste à écrire l'import, puis à lancer go mod tidy.
Faut-il committer go.sum ?
Oui. go.sum contient les empreintes cryptographiques de chaque version de module utilisée par votre build. Le committer permet à la commande go de vérifier que tout le monde télécharge des dépendances identiques à l'octet près. Ne le modifiez jamais à la main ; go mod tidy l'entretient.
« golang init », est-ce la même chose que go mod init ?
Non, ce sont deux choses différentes qui partagent un mot. go mod init est une commande de terminal qui crée go.mod. func init() est une fonction que vous écrivez dans du code Go ; elle s'exécute automatiquement une fois, avant main, après l'initialisation des variables du package.