Il se trouve que les développeurs qui commencent tout juste à se familiariser avec Go rencontrent souvent le problème de choisir un répertoire de travail pour les projets Go. Ainsi, dans le chat de la conférence GolangConf , cette question a également été posée. Les nouveaux gophers se font souvent peur avec les mots GOPATH et GOROOT . Cependant, dans les guides de démarrage rapide avec la version actuelle de Go (1.13), ces deux mots «effrayants» ne sont pas du tout mentionnés.
Voyons pourquoi. Pour la pureté de l'expérience, j'ai déployé Ubuntu frais sur une machine virtuelle et installé Go selon les instructions du Wiki :
sudo add-apt-repository ppa:longsleep/golang-backports sudo apt-get update sudo apt-get install golang-go
Go 1.13 est installé et prêt à l'emploi:
$ go version go version go1.13 linux/amd64 $ which go /usr/bin/go $ whereis go go: /usr/bin/go /usr/lib/go /usr/share/go /usr/share/man/man1/go.1.gz
GOROOT
A propos de GOROOT
a déjà été parfaitement écrit dans un article de 2015 , et cette information est toujours d'actualité.
C'est drôle que parmi la liste des répertoires émis par la dernière commande ( whereis go
), GOROOT
n'est en fait pas:
$ go env GOROOT /usr/lib/go-1.13
Ainsi, par exemple, si pour l'IDE j'ai besoin de spécifier le chemin d'accès aux fichiers de la bibliothèque Go standard, je spécifierai /usr/lib/go-1.13
. Peut-être que dans ce scénario, l'utilisation de GOROOT
dans la vie quotidienne prend fin.
GOPATH et modules
Il semblerait qu'à cet endroit il faut se précipiter pour installer GOPATH
, mais je ne le ferai pas. En fait, GOPATH
déjà défini:
$ go env GOPATH /home/elena/go
Je suis à l'aise avec l' GOPATH
dans ~/go
, ce qui signifie que je ne la changerai pas.
Je vais immédiatement créer un répertoire pour mon premier projet sur Go. Cela peut être fait n'importe où, par exemple, directement dans votre répertoire personnel. De plus, je vais immédiatement commencer à travailler avec l'outil Go Modules :
$ mkdir ~/hello $ go mod init github.com/rumyantseva/hello go: creating new go.mod: module github.com/rumyantseva/hello
Pour la commande go mod init
, j'ai spécifié un chemin de module de module unique pour mon projet. De cette façon, un proxy ou un autre outil, si nécessaire, peut retrouver les fichiers de mon projet.
Après avoir appelé la commande go mod init
, le répertoire go mod init
est apparu dans mon répertoire personnel:
$ tree ~/go /home/elena/go └── pkg └── mod └── cache └── lock 3 directories, 1 file
Dans ce cas, le fichier de verrouillage (tout en bas de l'arborescence) est toujours vide.
Le fichier go.mod
est apparu dans le go.mod
~/hello
avec le contenu suivant:
module github.com/rumyantseva/hello go 1.13
C'est dans go.mod
que toutes les informations sur les dépendances de mon module seront ensuite stockées.
Écrivons maintenant une application en utilisant une dépendance externe. Dans le répertoire ~/hello
, je crée le fichier main.go
et y écris le code suivant:
package main import ( "github.com/sirupsen/logrus" ) func main() { logrus.Info("Hello, world!") }
Bien sûr, dans la vraie vie pour écrire "Bonjour, monde!" Vous pouvez vous passer de logrus , mais dans cet exemple, cette bibliothèque nous aidera à savoir où sont stockés les fichiers des dépendances externes.
Je lance l'application de la manière la plus simple:
$ go run main.go go: finding github.com/sirupsen/logrus v1.4.2 go: downloading github.com/sirupsen/logrus v1.4.2 go: extracting github.com/sirupsen/logrus v1.4.2 go: downloading golang.org/x/sys v0.0.0-20190422165155-953cdadca894 go: extracting golang.org/x/sys v0.0.0-20190422165155-953cdadca894 go: finding golang.org/x/sys v0.0.0-20190422165155-953cdadca894 INFO[0000] Hello, world!
Avant la création et le lancement de l'application, l'outil go mod
fonctionnait. Il a défini ma dépendance externe github.com/sirupsen/logrus
, a pris sa dernière version v1.4.2
pour le moment et a v1.4.2
pour les dépendances transitives.
Une ligne a été ajoutée au fichier go.mod
avec une description de la dépendance de logrus
:
module github.com/rumyantseva/hello go 1.13 require github.com/sirupsen/logrus v1.4.2 // indirect
Le fichier go.sum
est également apparu, dans lequel, en plus du hachage de la dépendance logrus
, des informations sur les hachages des dépendances transitives sont stockées:
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Où est le code de dépendance lui-même? Il peut être trouvé dans ~/go/pkg/mod
. De plus, les sommes de contrôle et autres informations de surcharge pour travailler avec les dépendances seront stockées dans ~/go/pkg
.
Si vous avez déjà rencontré l'outil go get
, vous savez que lors de l'extraction de dépendances, il clone en fait les référentiels (par exemple, dans le cas de git avec git clone
). Mais go mod
ne fonctionne pas de cette façon. Pour go mod
unité de code principale est le module. Les modules sont des archives. Lorsque vous travaillez avec des dépendances de go mod
, il go mod download
explicitement (si vous avez appelé la commande go mod download
) ou implicitement (si vous avez commencé à compiler l'application) et décompresse les archives via GOPROXY
. Voyons comment le proxy est défini dans Go 1.13 par défaut:
$ go env GOPROXY https://proxy.golang.org,direct
Donc, en tant que proxy lors de la construction de mon "Bonjour, monde!" utilisé par proxy.golang.org . Bien entendu, cette variable peut être modifiée en choisissant un autre référentiel de modules. Par exemple, vous pouvez déployer votre propre société de proxy interne, qui sera stockée, y compris les bibliothèques internes, dont le code n'a pas été publié en open source.
En général, si je démarre un nouveau projet et que cela ne me dérange pas d'utiliser des modules Go, je ne sais peut-être rien de GOPATH
. Go créera le répertoire ~/go
par lui-même lorsque cela sera nécessaire.
Quand GOPATH est-il nécessaire?
Si vous n'utilisez pas essentiellement les modules Go (par exemple, dans un projet hérité), GOPATH
peut être GOPATH
de s'éloigner d'un travail plus explicite avec GOPATH
.
Pour voir ce qui va arriver à mon projet, si je décide de ne pas utiliser go mod
, supprimez les fichiers ~/hello/go.mod
et ~/hello/go.sum
. Je supprimerai également ~/go
pour revenir à l'état du système que j'avais au tout début:
rm -rf ~/go ~/hello/go.mod ~/hello/go.sum
Seul le fichier main.go
reste dans le main.go
~/hello
. Que se passe-t-il maintenant si j'essaye de l'exécuter avec go run
?
$ go run main.go main.go:4:2: cannot find package "github.com/sirupsen/logrus" in any of: /usr/lib/go-1.13/src/github.com/sirupsen/logrus (from $GOROOT) /home/elena/go/src/github.com/sirupsen/logrus (from $GOPATH)
Les voici, ces effrayants GOROOT
et GOPATH
:)
Afin de compiler l'application, j'ai besoin de récupérer la dépendance dans GOPATH
. Je fais ça avec le bon vieux go get
:
$ go get -v github.com/sirupsen/logrus github.com/sirupsen/logrus (download) created GOPATH=/home/elena/go; see 'go help gopath' get "golang.org/x/sys/unix": found meta tag get.metaImport{Prefix:"golang.org/x/sys", VCS:"git", RepoRoot:"https://go.googlesource.com/sys"} at //golang.org/x/sys/unix?go-get=1 get "golang.org/x/sys/unix": verifying non-authoritative meta tag golang.org/x/sys (download) golang.org/x/sys/unix github.com/sirupsen/logrus
Qu'est-il arrivé? Tout d'abord, go get
créer le répertoire ~/go
(celui spécifié comme GOPATH
). Ensuite, le processus de clonage des référentiels avec dépendances a commencé. C'est drôle que le clonage des référentiels soit sensiblement plus lent que l'option lorsque nous avons utilisé go mod
pour télécharger et décompresser les modules. Cependant, le code de dépendance peut maintenant être trouvé dans ~/go/src/
.
Soit dit en passant, il n'y avait toujours pas de client git sur mon propre installation d'Ubuntu, et pour go get
travailler, j'ai dû l'installer.
Je lance l'application:
$ go run main.go INFO[0000] Hello, world!
Ça marche!
C'est juste au niveau de l'application, je ne fais plus le suivi de la version des dépendances externes. Et si, en raison d'une vulnérabilité, à un moment donné dans le référentiel github.com/sirupsen/logrus
, ce n'est pas l'enregistreur que j'attendais, mais du code malveillant? Tôt ou tard, j'ai toujours besoin d'un outil pour travailler avec les dépendances, et si les modules Go pour une raison quelconque ne conviennent pas, vous devez chercher autre chose ...
Conclusion
Cet article n'a pas abordé certains points spécifiques, et travailler avec des dépendances externes dans Go peut toujours poser beaucoup de questions. Cependant, les nouvelles versions de Go au moins n'imposent pas de restrictions sur l'endroit où les répertoires de travail de vos projets peuvent être créés.
Si vous démarrez un nouveau projet, essayez Go Modules! Revenir à l'ancienne approche de l'utilisation des dépendances n'a de sens que si quelque chose ne va pas. Par ailleurs, si vous préférez stocker toutes les dépendances à l'intérieur du projet, Go Modules prend en charge le mode fournisseur.
Si vous devez travailler avec un projet existant, et pour une raison quelconque, vous ne voulez pas le traduire en modules Go, il est important d'indiquer les caractéristiques de son déploiement et de la gestion des dépendances dans la documentation du projet. Si les nouveaux arrivants qui ne connaissent pas les anciennes approches de travail avec les dépendances viennent au projet, il leur sera beaucoup plus facile de gérer le projet si toute la documentation est en place.
Soit dit en passant, le 7 octobre à la conférence de GolangConf , dans le cadre de l'une des activités spéciales, nous prévoyons une zone d'experts où chacun pourra poser des questions sur Go aux membres du comité du programme de la conférence et aux passionnés de la communauté russe de Go. Installer Go? Traitez les dépendances? Écrire un microservice? C'est pour nous!