Modules
Chaque langage moderne dispose de son propre outil de gestion des dépendances mature, tel que Gradle pour Java, Pip pour Python, Npm pour NodeJs, etc. Un bon outil de gestion des dépendances peut faire gagner beaucoup de temps aux développeurs et améliorer l'efficacité du développement. Cependant, Go ne disposait pas d'une solution de gestion des dépendances mature à ses débuts. À cette époque, tout le code était stocké dans le répertoire GOPATH, ce qui n'était pas très convivial pour les projets d'ingénierie, avec des versions chaotiques et des dépendances difficiles à gérer. Pour résoudre ce problème, les développeurs de la communauté ont proposé diverses solutions, créant une situation confuse. Parmi celles-ci, certaines solutions se sont démarquées, comme Vendor. Jusqu'à ce que Go 1.11 introduise officiellement Go Mod, l'outil de gestion des dépendances officiel, mettant fin à la confusion précédente et s'améliorant continuellement dans les mises à jour suivantes, éliminant les anciens outils. Aujourd'hui, au moment de la rédaction de cet article, la version de Go est la 1.20, et presque tous les projets Go utilisent Go Mod. Ainsi, cet article ne présentera que Go Mod. L'équipe officielle a également rédigé une documentation très détaillée sur les modules Go : Référence des modules Go.
Écriture d'un module
Go Module est essentiellement basé sur VCS (Version Control System). Lorsque vous téléchargez des dépendances, vous exécutez en réalité des commandes VCS, comme git. Donc, si vous souhaitez partager une bibliothèque que vous avez écrite, il vous suffit de respecter les trois points suivants :
- Le dépôt de code source doit être accessible publiquement, et le VCS doit être l'un des suivants :
- git
- hg (Mercurial)
- bzr (Bazaar)
- svn
- fossil
- Être un projet go mod conforme aux normes
- Respecter les normes de versionnement sémantique
Ainsi, il vous suffit de développer normalement avec VCS et de taguer vos versions spécifiques avec des tags conformes aux normes. Les autres utilisateurs pourront alors télécharger votre bibliothèque via le nom du module. Nous allons démontrer les étapes de développement d'un module à l'aide d'un exemple.
Dépôt d'exemple : 246859/hello: say hello (github.com)
Préparation
Avant de commencer, assurez-vous que votre version est suffisamment récente pour prendre en charge complètement go mod (go >= 1.17) et que Go Module est activé. Utilisez la commande suivante pour vérifier s'il est activé :
$ go env GO111MODULES'il n'est pas activé, utilisez la commande suivante pour activer Go Module :
$ go env -w GO111MODULE=onCréation
Tout d'abord, vous avez besoin d'un dépôt de code source accessible publiquement. Il y a plusieurs choix, mais je recommande Github. Créez un nouveau projet nommé hello. Bien qu'il n'y ait pas de restrictions particulières sur le nom du dépôt, il est recommandé de ne pas utiliser de caractères spéciaux, car cela pourrait affecter le nom du module.

Une fois créé, vous pouvez voir que l'URL du dépôt est https://github.com/246859/hello, et le nom du module Go correspondant est github.com/246859/hello.

Ensuite, clonez-le localement et initialisez le module avec la commande go mod init :
$ git clone git@github.com:246859/hello.git
Cloning into 'hello'...
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (5/5), done.
$ cd hello && go mod init github.com/246859/hello
go: creating new go.mod: module github.com/246859/helloÉcriture
Vous pouvez maintenant commencer le développement. La fonctionnalité est très simple, avec une seule fonction :
// hello.go
package hello
import "fmt"
// Hello returns hello message
func Hello(name string) string {
if name == "" {
name = "world"
}
return fmt.Sprintf("hello %s!", name)
}Écrivez également un fichier de test pour les tests unitaires :
// hello_test.go
package hello_test
import (
"testing"
"fmt"
"github.com/246859/hello"
)
func TestHello(t *testing.T) {
data := "jack"
expected := fmt.Sprintf("hello %s!", data)
result := hello.Hello(data)
if result != expected {
t.Fatalf("expected result %s, but got %s", expected, result)
}
}Ensuite, écrivez un programme en ligne de commande pour afficher hello. La fonctionnalité est également très simple. Pour les programmes en ligne de commande, selon les normes, ils doivent être créés dans cmd/app_name/ du projet. Ainsi, les fichiers du programme en ligne de commande hello sont stockés dans le répertoire cmd/hello/, puis écrivez le code pertinent.
// cmd/hello/main.go
package main
import (
"flag"
"github.com/246859/hello"
"os"
)
var name string
func init() {
flag.StringVar(&name, "name", "world", "name to say hello")
}
func main() {
flag.Parse()
msg := hello.Hello(name)
_, err := os.Stdout.WriteString(msg)
if err != nil {
os.Stderr.WriteString(err.Error())
}
}Test
Après l'écriture, formatez le code source et testez :
$ go fmt && go vet ./...
$ go test -v .
=== RUN TestHello
--- PASS: TestHello (0.00s)
PASS
ok github.com/246859/hello 0.023sExécutez le programme en ligne de commande :
$ go run ./cmd/hello -name jack
hello jack!Documentation
Enfin, écrivez un README clair et concis pour cette bibliothèque, afin que les autres développeurs sachent comment l'utiliser en un coup d'œil :
# hello
just say hello
## Install
import code
```bash
go get github.com/246859/hello@latest
```
install cmd
```bash
go install github.com/246859/hello/cmd/hello@latest
```
## Example
Here's a simple example as follows:
```go
package main
import (
"fmt"
"github.com/246859/hello"
)
func main() {
result := hello.Hello("jack")
fmt.Println(result)
}
```Ceci est un document README très simple, vous pouvez l'enrichir vous-même.
Téléversement
Lorsque tout le code est écrit et testé, vous pouvez soumettre les modifications et les pousser vers le dépôt distant.
$ git add go.mod hello.go hello_test.go cmd/ example/ README.md
$ git commit -m "chore(mod): mod init" go.mod
[main 5087fa2] chore(mod): mod init
1 file changed, 3 insertions(+)
create mode 100644 go.mod
$ git commit -m "feat(hello): complete Hello func" hello.go
[main 099a8bf] feat(hello): complete Hello func
1 file changed, 11 insertions(+)
create mode 100644 hello.go
$ git commit -m "test(hello): complete hello testcase" hello_test.go
[main 76e8c1e] test(hello): complete hello testcase
1 file changed, 17 insertions(+)
create mode 100644 hello_test.go
$ git commit -m "feat(hello): complete hello cmd" cmd/hello/
[main a62a605] feat(hello): complete hello cmd
1 file changed, 22 insertions(+)
create mode 100644 cmd/hello/main.go
$ git commit -m "docs(example): add hello example" example/
[main 5c51ce4] docs(example): add hello example
1 file changed, 11 insertions(+)
create mode 100644 example/main.go
$ git commit -m "docs(README): update README" README.md
[main e6fbc62] docs(README): update README
1 file changed, 27 insertions(+), 1 deletion(-)Six commits au total, ce n'est pas beaucoup. Après la soumission, créez un tag pour le dernier commit :
$ git tag v1.0.0
$ git tag -l
v1.0.0
$ git log --oneline
e6fbc62 (HEAD -> main, tag: v1.0.0, origin/main, origin/HEAD) docs(README): update README
5c51ce4 docs(example): add hello example
a62a605 feat(hello): complete hello cmd
76e8c1e test(hello): complete hello testcase
099a8bf feat(hello): complete Hello func
5087fa2 chore(mod): mod init
1f422d1 Initial commitEnfin, poussez vers le dépôt distant :
$ git push --tags
Enumerating objects: 23, done.
Counting objects: 100% (23/23), done.
Delta compression using up to 16 threads
Compressing objects: 100% (17/17), done.
Writing objects: 100% (21/21), 2.43 KiB | 1.22 MiB/s, done.
Total 21 (delta 5), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (5/5), done.
To github.com:246859/hello.git
1f422d1..e6fbc62 main -> main
* [new tag] v1.0.0 -> v1.0.0Après avoir poussé, créez une release (un tag suffit, la release est juste pour respecter les normes Github) :

Ainsi, l'écriture du module est terminée. Ce qui précède est le processus de base du développement d'un module. Les autres développeurs peuvent maintenant importer le code ou installer les outils en ligne de commande via le nom du module.
Importation
Importez la bibliothèque avec go get :
$ go get github.com/246859/hello@latest
go: downloading github.com/246859/hello v1.0.0
go: added github.com/246859/hello v1.0.0Installez le programme en ligne de commande avec go install :
$ go install github.com/246859/hello/cmd/hello@latest && hello -name jack
hello jack!Ou exécutez directement avec go run :
$ go run -mod=mod github.com/246859/hello/cmd/hello -name jack
hello jack!Lorsqu'une bibliothèque est importée, Go Package crée automatiquement une page pour elle. Ce processus est automatique et ne nécessite aucun travail de la part du développeur. Par exemple, la bibliothèque hello dispose d'une page de documentation exclusive, comme illustré ci-dessous.

Pour plus de détails sur le téléversement de modules, consultez Ajouter un package.
Pour savoir comment supprimer les informations d'un module, consultez Supprimer un package.
Configuration du proxy
Bien que Go ne dispose pas d'un dépôt central similaire à Maven Repo, PyPi ou NPM, il existe un dépôt proxy officiel : Services de modules Go (golang.org). Il met en cache les modules téléchargés par les développeurs en fonction de la version et du nom du module. Cependant, comme ses serveurs sont déployés à l'étranger, la vitesse d'accès n'est pas très conviviale pour les utilisateurs nationaux. Nous devons donc modifier l'adresse du proxy de module par défaut. Actuellement, les meilleurs en Chine sont les suivants :

Ici, nous choisissons le proxy de Qiniu Cloud. Exécutez la commande suivante pour modifier le proxy Go, où direct signifie que si le téléchargement via le proxy échoue, il contourne le cache du proxy pour accéder directement au dépôt de code source.
$ go env -w GOPROXY=https://goproxy.cn,directUne fois le proxy modifié avec succès, le téléchargement des dépendances sera très rapide à l'avenir.
Téléchargement des dépendances
Après avoir modifié le proxy, essayons d'installer une dépendance tierce. Go dispose d'un site web dédié à la recherche de dépendances : Go Packages.
Importation de code
Recherchez le célèbre framework Web Gin dedans.

De nombreux résultats de recherche apparaîtront. Lors de l'utilisation de dépendances tierces, il faut décider d'adopter ou non la dépendance en fonction du nombre de citations et de la date de mise à jour. Ici, nous choisissons directement le premier :

Après être entré dans la page correspondante, vous pouvez voir qu'il s'agit d'une page de documentation de la dépendance, avec beaucoup d'informations détaillées à son sujet. Vous pouvez également y consulter la documentation ultérieurement.

Il suffit de copier son adresse, puis d'utiliser la commande go get dans le projet créé précédemment, comme suit :
$ go get github.com/gin-gonic/ginDe nombreuses dépendances seront téléchargées pendant le processus. Tant qu'il n'y a pas d'erreur, le téléchargement a réussi.
$ go get github.com/gin-gonic/gin
go: added github.com/bytedance/sonic v1.8.0
go: added github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311
go: added github.com/gin-contrib/sse v0.1.0
go: added github.com/gin-gonic/gin v1.9.0
go: added github.com/go-playground/locales v0.14.1
go: added github.com/go-playground/universal-translator v0.18.1
go: added github.com/go-playground/validator/v10 v10.11.2
go: added github.com/goccy/go-json v0.10.0
go: added github.com/json-iterator/go v1.1.12
go: added github.com/klauspost/cpuid/v2 v2.0.9
go: added github.com/leodido/go-urn v1.2.1
go: added github.com/mattn/go-isatty v0.0.17
go: added github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421
go: added github.com/modern-go/reflect2 v1.0.2
go: added github.com/pelletier/go-toml/v2 v2.0.6
go: added github.com/twitchyliquid64/golang-asm v0.15.1
go: added github.com/ugorji/go/codec v1.2.9
go: added golang.org/x/arch v0.0.0-20210923205945-b76863e36670
go: added golang.org/x/crypto v0.5.0
go: added golang.org/x/net v0.7.0
go: added golang.org/x/sys v0.5.0
go: added golang.org/x/text v0.7.0
go: added google.golang.org/protobuf v1.28.1
go: added gopkg.in/yaml.v3 v3.0.1Après avoir terminé, consultez le fichier go.mod :
$ cat go.mod
module golearn
go 1.20
require github.com/gin-gonic/gin v1.9.0
require (
github.com/bytedance/sonic v1.8.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.11.2 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)Vous pouvez constater qu'il y a beaucoup plus de choses qu'auparavant, et vous remarquerez également qu'un fichier nommé go.sum est apparu dans le répertoire :
$ ls
go.mod go.sum main.goNous y reviendrons plus tard. Modifiez le fichier main.go avec le code suivant :
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
gin.Default().Run()
}Exécutez à nouveau le projet :
$ go run golearn
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080Ainsi, avec une seule ligne de code, nous avons lancé un serveur Web des plus simples. Lorsqu'une dépendance n'est plus nécessaire, vous pouvez également utiliser la commande go get pour la supprimer. Prenons l'exemple de la suppression de Gin :
$ go get github.com/gin-gonic/gin@none
go: removed github.com/gin-gonic/gin v1.9.0Ajoutez @none après l'adresse de la dépendance pour la supprimer. Le résultat indique que la suppression a réussi. En consultant à nouveau le fichier go.mod, vous constaterez que la dépendance Gin a disparu.
$ cat go.mod | grep github.com/gin-gonic/ginPour mettre à niveau vers la dernière version, ajoutez le suffixe @latest, ou vous pouvez rechercher vous-même les numéros de version Release disponibles :
$ go get -u github.com/gin-gonic/gin@latestInstallation en ligne de commande
La commande go install télécharge la dépendance tierce localement et la compile en un fichier binaire. Grâce à la vitesse de compilation de Go, ce processus ne prend généralement pas beaucoup de temps. Ensuite, Go le stocke dans le répertoire $GOPATH/bin ou $GOBIN, afin qu'il puisse être exécuté globalement (à condition que vous ayez ajouté ces chemins aux variables d'environnement).
TIP
Lors de l'utilisation de la commande install, vous devez spécifier un numéro de version.
Par exemple, téléchargez le débogueur delve écrit en Go :
$ go install github.com/go-delve/delve/cmd/dlv@latest
go: downloading github.com/go-delve/delve v1.22.1
go: downloading github.com/cosiner/argv v0.1.0
go: downloading github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d
go: downloading github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62
go: downloading github.com/google/go-dap v0.11.0
go: downloading github.com/hashicorp/golang-lru v1.0.2
go: downloading golang.org/x/arch v0.6.0
go: downloading github.com/cpuguy83/go-md2man/v2 v2.0.2
go: downloading go.starlark.net v0.0.0-20231101134539-556fd59b42f6
go: downloading github.com/cilium/ebpf v0.11.0
go: downloading github.com/mattn/go-runewidth v0.0.13
go: downloading github.com/russross/blackfriday/v2 v2.1.0
go: downloading github.com/rivo/uniseg v0.2.0
go: downloading golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2
$ dlv -v
Error: unknown shorthand flag: 'v' in -v
Usage:
dlv [command]
Available Commands:
attach Attach to running process and begin debugging.
completion Generate the autocompletion script for the specified shell
connect Connect to a headless debug server with a terminal client.
core Examine a core dump.
dap Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).
debug Compile and begin debugging main package in current directory, or the package specified.
exec Execute a precompiled binary, and begin a debug session.
help Help about any command
test Compile test binary and begin debugging program.
trace Compile and begin tracing program.
version Prints version.
Additional help topics:
dlv backend Help about the --backend flag.
dlv log Help about logging flags.
dlv redirect Help about file redirection.
Use "dlv [command] --help" for more information about a command.Gestion des modules
Tout ce qui précède ne fait que décrire l'utilisation de base de Go Mod, mais en réalité, apprendre Go Mod ne se limite pas à cela. La définition officielle d'un module est : un ensemble de packages marqués par une version. Dans la définition ci-dessus, le concept de package devrait être familier, et la version doit suivre le versionnement sémantique, défini au format v(majeur).(mineur).(correctif). Par exemple, la version de Go v1.20.1, le numéro de version majeur est 1, le numéro de version mineur est 20, le numéro de correctif est 1, ce qui donne v1.20.1. Voici des explications plus détaillées :
majeur: Lorsque la version majeure change, cela signifie que le projet a subi des modifications incompatibles. Les projets anciens mis à niveau vers la nouvelle version ne fonctionneront probablement pas correctement.mineur: Lorsque la versionmineurechange, cela signifie que le projet a ajouté de nouvelles fonctionnalités, basées sur la version précédente.correctif: Lorsque la versioncorrectifchange, cela signifie simplement que des bugs ont été corrigés, sans ajouter de nouvelles fonctionnalités.
Commandes courantes
| Commande | Description |
|---|---|
go mod download | Télécharge les dépendances du projet actuel |
go mod edit | Édite le fichier go.mod |
go mod graph | Affiche le graphe des dépendances du module |
go mod init | Initialise go mod dans le répertoire actuel |
go mod tidy | Nettoie les modules du projet |
go mod verify | Vérifie la légalité des dépendances du projet |
go mod why | Explique où le projet utilise les dépendances |
go clean -modcache | Supprime le cache des dépendances du projet |
go list -m | Liste les modules |
Consultez commande go mod pour plus d'informations sur les commandes.
Stockage des modules
Lors de l'utilisation de Go Mod pour la gestion de projet, le cache des modules est stocké par défaut dans le répertoire $GOPATH/pkg/mod. Vous pouvez également modifier $GOMODCACHE pour le stocker à un autre emplacement.
$ go env -w GOMODCACHE=votre_chemin_de_cache_moduleTous les projets Go Module sur la même machine partagent le cache de ce répertoire. Le cache n'a pas de limite de taille et n'est pas automatiquement supprimé. Les fichiers source des dépendances décompressés dans le cache sont en lecture seule. Pour vider le cache, exécutez la commande suivante :
$ go clean -modcacheLe répertoire $GOMODCACHE/cache/download contient les fichiers originaux des dépendances, y compris les fichiers de hachage, les archives originales, etc. Par exemple :
$ ls $(go env GOMODCACHE)/cache/download/github.com/246859/hello/@v -1
list
v1.0.0.info
v1.0.0.lock
v1.0.0.mod
v1.0.0.zip
v1.0.0.ziphashL'organisation des dépendances après décompression est la suivante, c'est-à-dire le code source du module spécifié :
$ ls $(go env GOMODCACHE)/github.com/246859/hello@v1.0.0 -1
LICENSE
README.md
cmd/
example/
go.mod
hello.go
hello_test.goSélection de version
Lors de la sélection des versions de dépendances, Go suit le principe de sélection de version minimale. Voici un exemple du site officiel : le module principal importe la version 1.2 du module A et la version 1.2 du module B. La version 1.2 du module A importe la version 1.3 du module C, et la version 1.2 du module B importe la version 1.4 du module C. Les versions 1.3 et 1.4 du module C importent toutes deux la version 1.2 du module D. Selon le principe de version minimale utilisable, Go sélectionnera finalement les versions A1.2, B1.2, C1.4 et D1.2. Parmi celles-ci, le bleu clair indique les fichiers go.mod chargés, et les cases indiquent les versions finalement sélectionnées.
Le site officiel fournit également d'autres exemples, qui sont globalement similaires.
go.mod
Chaque création d'un projet Go Mod génère un fichier go.mod, il est donc nécessaire de se familiariser avec ce fichier, bien que dans la plupart des cas, il ne soit pas nécessaire de le modifier manuellement.
module golearn
go 1.20
require github.com/gin-gonic/gin v1.9.0
require (
github.com/bytedance/sonic v1.8.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.11.2 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)Dans le fichier, vous pouvez constater que la plupart des adresses de dépendances contiennent des termes comme github. Cela est dû au fait que Go ne dispose pas d'un dépôt de dépendances public. La plupart des projets open source sont hébergés sur GitHub, tandis que certains ont leurs propres dépôts, comme google.golang.org/protobuf et golang.org/x/crypto. En général, cette série d'URL est également le nom du module du projet Go, ce qui pose un problème : les URL ne distinguent pas les majuscules des minuscules, mais les répertoires de stockage des dépendances les distinguent. Ainsi, go get github.com/gin-gonic/gin et go get github.com/gin-gonic/Gin importent la même dépendance, mais le chemin de stockage local est différent. Dans ce cas, Go ne prend pas directement les lettres majuscules comme chemin de stockage, mais les échappe en !lettre minuscule. Par exemple, github.com\BurntSushi sera finalement échappé en github.com\!burnt!sushi.
module
Le mot-clé module déclare le nom du module du projet actuel. Un fichier go.mod ne peut contenir qu'un seul mot-clé module. Dans l'exemple :
module golearnCela signifie que le nom du module actuel est golearn. Par exemple, en ouvrant le fichier go.mod de la dépendance Gin, vous pouvez trouver son nom de module :
module github.com/gin-gonic/ginLe nom du module de Gin est l'adresse utilisée lors du téléchargement de la dépendance. C'est également le format recommandé pour les noms de modules : domaine/utilisateur/dépôt.
TIP
Un point important à noter est que lorsque la version majeure est supérieure à 1, le numéro de version majeur doit être inclus dans le nom du module. Par exemple :
github.com/my/exampleSi la version est mise à niveau vers v2.0.0, le nom du module doit être modifié comme suit :
github.com/my/example/v2Si un projet existant importe l'ancienne version et que la nouvelle version n'est pas différenciée, lors de l'importation de la dépendance, comme les chemins sont identiques, l'utilisateur ne peut pas distinguer les changements incompatibles dus aux modifications de la version majeure, ce qui peut entraîner des erreurs de programme.
Deprecation
Commentez Deprecated au début de la ligne précédente de module pour indiquer que le module est déprécié. Par exemple :
// Deprecated: use example.com/mod/v2 instead.
module example.com/modgo
Le mot-clé go indique la version de Go utilisée pour écrire le projet actuel. Le numéro de version doit suivre les règles de versionnement sémantique. Selon la version de Go, Go Mod se comportera différemment. Voici un exemple simple. Consultez la documentation officielle pour les versions de Go disponibles.
go 1.20require
Le mot-clé require indique qu'une dépendance externe est importée. Par exemple :
require github.com/gin-gonic/gin v1.9.0Le format est require nom_du_module version. S'il y a plusieurs importations, vous pouvez les regrouper entre parenthèses :
require (
github.com/bytedance/sonic v1.8.0 // indirect
)Les dépendances avec le commentaire // indirect signifient qu'elles ne sont pas directement importées par le projet actuel. Elles peuvent être importées par les dépendances directement importées par le projet, donc elles sont des importations indirectes pour le projet actuel. Comme mentionné précédemment, les changements de version majeure doivent être reflétés dans le nom du module. Les modules qui ne respectent pas cette règle sont appelés modules non conformes. Lors de l'importation avec require, un commentaire incompatible sera ajouté.
require example.com/m v4.1.2+incompatiblePseudo-version
Dans le fichier go.mod ci-dessus, vous pouvez constater que certaines versions de dépendances ne sont pas des numéros de version sémantiques, mais une série de chaînes incompréhensibles. Il s'agit en réalité du CommitID de la version correspondante. Les versions sémantiques font généralement référence à une Release. Les pseudo-versions peuvent spécifier un Commit particulier. Le format est généralement vx.y.z-yyyyMMddHHmmss-CommitId. Comme son vx.y.z n'existe pas nécessairement réellement, on l'appelle pseudo-version. Par exemple, dans l'exemple ci-dessous, v0.0.0 n'existe pas, seuls les 12 chiffres du CommitID suivants sont valides.
// CommitID prend généralement les 12 premiers caractères
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirectDe même, lors du téléchargement de dépendances, vous pouvez spécifier le CommitID pour remplacer le numéro de version sémantique :
go get github.com/chenzhuoyu/base64x@fe3a3abad311exclude
Le mot-clé exclude indique de ne pas charger une version spécifique de dépendance. Si require importe également la même version de dépendance, elle sera ignorée. Ce mot-clé n'est effectif que dans le module principal. Par exemple :
exclude golang.org/x/net v1.2.3
exclude (
golang.org/x/crypto v1.4.5
golang.org/x/text v1.6.7
)replace
replace remplacera une version spécifique de dépendance. Vous pouvez utiliser le chemin et la version du module pour remplacer, ou un chemin de fichier local spécifié. Exemple :
replace golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
replace (
golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
golang.org/x/net => example.com/fork/net v1.4.5
golang.org/x/net v1.2.3 => ./fork/net
golang.org/x/net => ./fork/net
)Seule la version à gauche de => est remplacée. Les autres versions de la même dépendance peuvent toujours être accessibles normalement. Que vous utilisiez un chemin local ou un chemin de module pour spécifier le remplacement, si le module de remplacement possède un fichier go.mod, sa directive module doit correspondre au chemin du module remplacé.
retract
La directive retract indique qu'il ne faut pas dépendre des versions ou plages de versions spécifiées par retract. Par exemple, si un problème majeur est découvert après la publication d'une nouvelle version, vous pouvez utiliser la directive retract.
Retirer certaines versions :
retract (
v1.0.0 // Published accidentally.
v1.0.1 // Contains retractions only.
)Retirer une plage de versions :
retract v1.0.0
retract [v1.0.0, v1.9.9]
retract (
v1.0.0
[v1.0.0, v1.9.9]
)go.sum
Le fichier go.sum n'existe pas lors de la création initiale d'un projet. Il est généré uniquement lorsque des dépendances externes sont réellement importées. Le fichier go.sum n'est pas adapté à la lecture humaine et il n'est pas recommandé de le modifier manuellement. Son rôle principal est de résoudre les problèmes de construction cohérente, c'est-à-dire que différentes personnes dans différents environnements utilisant le même projet doivent importer exactement les mêmes dépendances lors de la construction. Cela ne peut pas être garanti uniquement par un fichier go.mod.
Voyons maintenant ce que fait Go du début à la fin lors du téléchargement d'une dépendance. Tout d'abord, utilisez la commande suivante pour télécharger une dépendance :
go get github.com/bytedance/sonic v1.8.0La commande go get commence par télécharger le package de dépendance dans le répertoire de cache local, généralement $GOMODCACHE/cache/download/. Ce répertoire divise les dépendances de différents sites Web par nom de domaine, vous pourriez donc voir la structure de répertoire suivante :
$ ls
cloud.google.com/ go.opencensus.io/ gopkg.in/ nhooyr.io/
dmitri.shuralyov.com/ go.opentelemetry.io/ gorm.io/ rsc.io/
github.com/ go.uber.org/ honnef.co/ sumdb/
go.etcd.io/ golang.org/ lukechampine.com/
go.mongodb.org/ google.golang.org/ modernc.org/Ainsi, le chemin de stockage de la dépendance téléchargée dans l'exemple ci-dessus est :
$GOMODCACHE/cache/download/github.com/bytedance/sonic/@v/La structure de répertoire possible est la suivante, avec plusieurs fichiers nommés par version :
$ ls
list v1.8.0.lock v1.8.0.ziphash v1.8.3.mod
v1.5.0.mod v1.8.0.mod v1.8.3.info v1.8.3.zip
v1.8.0.info v1.8.0.zip v1.8.3.lock v1.8.3.ziphashEn général, il doit y avoir un fichier list dans ce répertoire, utilisé pour enregistrer les numéros de version connus de la dépendance. Pour chaque version, il y aura les fichiers suivants :
zip: archive source de la dépendanceziphash: valeur de hachage calculée à partir de l'archive de la dépendanceinfo: métadonnées de version au format JSONmod: fichiergo.modde cette versionlock: fichier temporaire, l'officiel n'a pas expliqué à quoi il sert
En général, Go calcule les valeurs de hachage des deux fichiers, l'archive et go.mod, puis interroge la valeur de hachage de la dépendance sur le serveur spécifié par GOSUMDB (par défaut sum.golang.org). Si la valeur de hachage calculée localement ne correspond pas au résultat de la requête, l'exécution ne se poursuivra pas. Si elles correspondent, Go mettra à jour le fichier go.mod et insérera deux entrées dans le fichier go.sum, comme suit :
github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=TIP
Si GOSUMDB est désactivé, Go écrira directement la valeur de hachage calculée localement dans le fichier go.sum. Il n'est généralement pas recommandé de faire cela.
Normalement, chaque dépendance aura deux entrées : la première est la valeur de hachage de l'archive, la seconde est la valeur de hachage du fichier go.mod de la dépendance. Le format d'enregistrement est nom_du_module version nom_algorithme:valeur_de_hachage. Certaines dépendances plus anciennes peuvent ne pas avoir de fichier go.mod, donc il n'y aura pas de deuxième entrée de hachage. Lorsque ce projet est construit dans un autre environnement, Go calculera la valeur de hachage des dépendances locales spécifiées dans go.mod et la comparera avec les valeurs de hachage enregistrées dans go.sum. Si les valeurs de hachage ne correspondent pas, cela signifie que les versions de dépendances sont différentes et la construction sera refusée. Dans ce cas, les dépendances locales et le fichier go.sum peuvent avoir été modifiés, mais comme go.sum est enregistré après une requête GOSUMDB, Go aura tendance à faire davantage confiance au fichier go.sum.
Modules privés
La plupart des outils Go Mod sont destinés aux projets open source, mais Go prend également en charge les modules privés. Pour les projets privés, il est généralement nécessaire de configurer les variables d'environnement suivantes pour gérer les modules privés :
GOPROXY: ensemble de serveurs proxy pour les dépendancesGOPRIVATE: liste de modèles génériques de préfixes de chemins de modules privés. Si le nom du module correspond aux règles, cela signifie que le module est un module privé. Le comportement est le même que GONOPROXY et GONOSUMDB.GONOPROXY: liste de modèles génériques de préfixes de chemins de modules qui ne sont pas téléchargés via le proxy. Si cela correspond, le téléchargement du module n'utilisera pas GOPROXY et tentera de télécharger directement depuis le système de contrôle de version.GONOSUMDB: liste de modèles génériques de préfixes de chemins de modules qui ne subissent pas de validation publique GOSUMDB. Si cela correspond, la validation du module n'utilisera pas la base de données publique de checksum.GOINSECURE: liste de modèles génériques de préfixes de chemins de modules qui peuvent être récupérés via HTTP et d'autres protocoles non sécurisés.
Espaces de travail
Comme mentionné précédemment, le fichier go.mod prend en charge la directive replace, ce qui nous permet d'utiliser temporairement des modifications locales qui n'ont pas encore été publiées, comme suit :
replace (
github.com/246859/hello v1.0.1 => ./hello
)Lors de la compilation, Go utilisera le module hello local, puis le supprimera lors de la publication d'une nouvelle version à l'avenir.
Cependant, l'utilisation de la directive replace modifiera le contenu du fichier go.mod, et cette modification pourrait être accidentellement soumise au dépôt distant. C'est quelque chose que nous ne souhaitons pas, car la cible spécifiée par la directive replace est un chemin de fichier et non une URL réseau. Le chemin qui fonctionne sur cette machine peut ne pas fonctionner sur une autre, et les chemins de fichiers posent également un problème important pour la compatibilité multiplateforme. Pour résoudre ce type de problèmes, les espaces de travail ont été créés.
Les espaces de travail (workspace) sont une nouvelle solution de gestion multi-module introduite par Go en 1.18, visant à mieux effectuer le développement multi-module local. Nous allons l'expliquer à l'aide d'un exemple.
Dépôt d'exemple : 246859/work: go work example (github.com)
Exemple
Tout d'abord, le projet contient deux modules Go indépendants, auth et user :
$ ls -1
LICENSE
README.md
auth
go.work
userLe module auth dépend de la structure User du module user, comme suit :
package auth
import (
"errors"
"github.com/246859/work/user"
)
// Verify user credentials if is ok
func Verify(user user.User) (bool, error) {
password, err := query(user.Name)
if err != nil {
return false, err
}
if password != user.Password {
return false, errors.New("authentication failed")
}
return true, nil
}
func query(username string) (string, error) {
if username == "jack" {
return "jack123456", nil
}
return "", errors.New("user not found")
}Le contenu du module user est le suivant :
package user
type User struct {
Name string
Password string
Age int
}Dans ce projet, nous pouvons écrire le fichier go.work comme suit :
go 1.22
use (
./auth
./user
)Le contenu est très facile à comprendre. Utilisez la directive use pour spécifier quels modules participent à la compilation. Ensuite, exécutez le code du module auth :
// auth/example/main.go
package main
import (
"fmt"
"github.com/246859/work/auth"
"github.com/246859/work/user"
)
func main() {
ok, err := auth.Verify(user.User{Name: "jack", Password: "jack123456"})
if err != nil {
panic(err)
}
fmt.Printf("%v", ok)
}Exécutez la commande suivante. Le résultat indique que le module a été importé avec succès.
$ go run ./auth/example
trueDans les versions précédentes, pour ces deux modules indépendants, si le module auth souhaitait utiliser le code du module user, il n'y avait que deux méthodes :
- Soumettre les modifications du module user et les pousser vers le dépôt distant, publier une nouvelle version, puis modifier le fichier
go.modpour la version spécifiée. - Modifier le fichier
go.modpour rediriger la dépendance vers un fichier local.
Les deux méthodes nécessitent de modifier le fichier go.mod. L'existence des espaces de travail vise à permettre l'importation d'autres modules sans modifier le fichier go.mod. Cependant, il est important de comprendre que le fichier go.work est utilisé uniquement pendant le développement. Son existence vise à faciliter le développement local, et non à gérer les dépendances. Il vous permet simplement de sauter temporairement le processus de soumission et de publication, vous permettant d'utiliser immédiatement les nouvelles modifications du module user sans attendre. Lorsque le module user est testé, vous devez toujours publier une nouvelle version, et le module auth doit toujours modifier le fichier go.mod pour importer la dernière version (ce processus peut être effectué avec la commande go work sync). Ainsi, dans le développement Go normal, go.work ne doit pas non plus être soumis au VCS (le go.work dans le dépôt d'exemple est uniquement à des fins de démonstration), car son contenu dépend des fichiers locaux et sa fonctionnalité est limitée au développement local.
Commandes
Voici quelques commandes d'espace de travail :
| Commande | Description |
|---|---|
| edit | Édite go.work |
| init | Initialise un nouvel espace de travail |
| sync | Synchronise les dépendances de module de l'espace de travail |
| use | Ajoute un nouveau module à go.work |
| vendor | Copie les dépendances au format vendor |
Consultez commande go work pour plus d'informations sur les commandes.
Directives
Le contenu du fichier go.work est très simple, avec seulement trois directives :
go, spécifie la version de Gouse, spécifie les modules à utiliserreplace, spécifie les modules à remplacer
À l'exception de la directive use, les deux autres sont essentiellement équivalentes aux directives dans go.mod, sauf que la directive replace dans go.work s'applique à tous les modules. Un go.work complet est le suivant :
go 1.22
use(
./auth
./user
)
replace github.com/246859/hello v1.0.0 => /home/jack/code/hello