190 votes

Allez construire : "Impossible de trouver le package" (même si GOPATH est défini)

Même si j'ai GOPATH correctement configuré, je n'arrive toujours pas à trouver mes propres packages avec "go build" ou "go run". Qu'est-ce que je fais de mal?

$ echo $GOROOT
/usr/local/go

$ echo $GOPATH
/home/mitchell/go

$ cat ~/main.go
package main
import "foobar"
func main() { }

$ cat /home/mitchell/go/src/foobar.go
package foobar

$ go build main.go
main.go:3:8: import "foobar": impossible de trouver le package

2 votes

Je rencontre le même problème lorsque je vais chercher github.com/adonovan/gopl.io/tree/master/ch1/helloworld La raison en est qu'il n'y a pas de fichier nommé helloworld.go. go get fonctionne en faisant correspondre le nom du package et le nom du fichier.

0 votes

Il se peut également que vous ayez besoin de mettre à jour Go. J'ai rencontré un problème similaire où j'avais du code existant utilisant go.mod pour définir un module. Sur une machine de test, j'avais téléchargé le code et j'essayais de le compiler mais Go me donnait toutes sortes d'erreurs liées à GOPATH et l'incapacité de trouver des modules. C'était la version Go 1.7. Dès que j'ai mis à jour Go, tout a fonctionné sans problème.

0 votes

Tapez ceci dans le terminal pour une explication à jour $ go help gopath

190voto

fasmat Points 431

Cela ne fonctionne pas car votre fichier source foobar.go n'est pas dans un répertoire appelé foobar. Les commandes go build et go install essaient de faire correspondre les répertoires, pas les fichiers source.

  1. Définissez $GOPATH sur un répertoire valide, par exemple export GOPATH="$HOME/go"
  2. Déplacez foobar.go dans $GOPATH/src/foobar/foobar.go et la compilation devrait fonctionner correctement.

Étapes recommandées supplémentaires :

  1. Ajoutez $GOPATH/bin à votre $PATH en tapant : PATH="$GOPATH/bin:$PATH"
  2. Déplacez main.go dans un sous-répertoire de $GOPATH/src, par exemple $GOPATH/src/test
  3. go install test devrait maintenant créer un exécutable dans $GOPATH/bin qui peut être appelé en tapant test dans votre terminal.

51voto

bostIT Points 171

Bien que la réponse acceptée soit toujours correcte en ce qui concerne le besoin de faire correspondre les répertoires avec les noms des packages, vous devez vraiment migrer vers l'utilisation des modules Go au lieu d'utiliser GOPATH. Les nouveaux utilisateurs qui rencontrent ce problème peuvent être confus au sujet des mentions de l'utilisation de GOPATH (comme je l'étais), qui sont maintenant obsolètes. Donc, je vais essayer de clarifier ce problème et de fournir des conseils associés pour éviter cette situation lors de l'utilisation des modules Go.

Si vous êtes déjà familiarisé avec les modules Go et que vous rencontrez ce problème, passez directement à mes sections plus spécifiques ci-dessous qui couvrent certaines des conventions Go faciles à négliger ou à oublier.

Ce guide explique les modules Go : https://golang.org/doc/code.html

Organisation du projet avec les modules Go

Une fois que vous migrez vers les modules Go, comme mentionné dans cet article, organisez le code du projet comme décrit :

Un dépôt contient un ou plusieurs modules. Un module est une collection de packages Go liés qui sont publiés ensemble. Un dépôt Go contient généralement un seul module, situé à la racine du dépôt. Un fichier nommé go.mod déclare le chemin du module: le préfixe du chemin d'importation pour tous les packages dans le module. Le module contient les packages dans le répertoire contenant son fichier go.mod ainsi que des sous-répertoires de ce répertoire, jusqu'au prochain sous-répertoire contenant un autre fichier go.mod (le cas échéant).

Le chemin de chaque module sert non seulement de préfixe du chemin d'importation pour ses packages, mais indique également où la commande go doit chercher pour le télécharger. Par exemple, pour télécharger le module golang.org/x/tools, la commande go consulterait le dépôt indiqué par https://golang.org/x/tools (décrit plus en détail ici).

Un chemin d'importation est une chaîne utilisée pour importer un package. Le chemin d'importation d'un package est son chemin de module joint à son sous-répertoire dans le module. Par exemple, le module github.com/google/go-cmp contient un package dans le répertoire cmp/. Le chemin d'importation de ce package est github.com/google/go-cmp/cmp. Les packages de la bibliothèque standard n'ont pas de préfixe de chemin de module.

Vous pouvez initialiser votre module de cette manière :

$ go mod init github.com/mitchell/foo-app

Votre code n'a pas besoin d'être situé sur github.com pour être compilé. Cependant, il est préférable de structurer vos modules comme s'ils devaient finalement être publiés.

Comprendre ce qui se passe lors de la tentative d'obtention d'un package

Un excellent article ici parle de ce qui se passe lorsque vous essayez d'obtenir un package ou un module : https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16 Il discute de l'endroit où le package est stocké et vous aidera à comprendre pourquoi vous pourriez rencontrer cette erreur si vous utilisez déjà des modules Go.

Assurez-vous que la fonction importée a été exportée

Remarquez que si vous avez des difficultés à accéder à une fonction d'un autre fichier, vous devez vous assurer d'avoir exporté votre fonction. Comme décrit dans le premier lien que j'ai fourni, une fonction doit commencer par une lettre majuscule pour être exportée et rendue disponible pour l'importation dans d'autres packages.

Noms de répertoires

Un autre détail crucial (comme mentionné dans la réponse acceptée) est que les noms des répertoires définissent les noms de vos packages. (Vos noms de package doivent correspondre à ceux de leurs répertoires.) Vous pouvez voir des exemples de cela ici : https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc Cela dit, le fichier contenant votre méthode main (c'est-à-dire le point d'entrée de votre application) est en quelque sorte exempt de cette exigence.

Par exemple, j'avais des problèmes avec mes imports lorsque j'utilisais une structure comme celle-ci :

/mon-app
 go.mod
 /src
    main.go
    /utils
       utils.go

Je ne pouvais pas importer le code dans utils dans mon package main.

Cependant, une fois que j'ai mis main.go dans son propre sous-répertoire, comme indiqué ci-dessous, mes imports ont fonctionné parfaitement :

/mon-app
 go.mod
 /src
    /app
   |   main.go
    /utils
       utils.go

Dans cet exemple, mon fichier go.mod ressemble à ceci :

module git.mydomain.com/path/to/repo/mon-app

go 1.14

Lorsque j'ai enregistré main.go après avoir ajouté une référence à utils.MyFunction(), mon IDE a automatiquement inclus la référence à mon package de cette manière :

import "git.mydomain.com/chemin/vers/repo/mon-app/src/mon-app"

(J'utilise VS Code avec l'extension Golang.)

Remarquez que le chemin d'importation incluait le sous-répertoire du package.

Gérer un référentiel privé

Si le code fait partie d'un référentiel privé, vous devez exécuter une commande git pour activer l'accès. Sinon, vous pouvez rencontrer d'autres erreurs. Cet article mentionne comment faire cela pour des référentiels privés Github, BitBucket et GitLab : https://medium.com/cloud-native-the-gathering/go-modules-with-private-git-repositories-dfe795068db4 Ce problème est également discuté ici : Quelle est la bonne manière de "go get" un référentiel privé ?

20voto

yuxuan li Points 181

J'ai résolu ce problème en configurant mon environnement go env GO111MODULE sur off

go env -w  GO111MODULE=off

Remarque : en définissant GO111MODULE=off, vous désactivez la dernière fonctionnalité des modules Go.

Référence : Pourquoi GO111MODULE est partout, et tout sur les modules Go (mis à jour avec Go 1.17)

GO111MODULE avec Go 1.16

A partir de Go 1.16, le comportement par défaut est GO111MODULE=on, ce qui signifie que si vous voulez continuer à utiliser l'ancienne méthode GOPATH, vous devrez forcer Go à ne pas utiliser la fonctionnalité des modules Go :

export GO111MODULE=off

13voto

Surya Points 393

Dans les versions récentes de go à partir de la version 1.14, nous devons exécuter go mod vendor avant de construire ou d'exécuter, car par défaut go ajoute -mod=vendor aux commandes go. Donc, après avoir exécuté go mod vendor, si nous essayons de construire, nous ne rencontrerons pas ce problème.

10voto

VonC Points 414372

Éditer: depuis que vous avez mentionné GOPATH, voir la réponse de fasmat (votée)

Comme mentionné dans "Comment faire en sorte que go trouve mon package?", vous devez mettre un package xxx dans un répertoire xxx.

Voir le spécification du langage Go:

package math

Un ensemble de fichiers partageant le même PackageName forment l'implémentation d'un package.
Une implémentation peut exiger que tous les fichiers source pour un package habitent le même répertoire.

La organisation du code mentionne:

Lors de la construction d'un programme qui importe le package "widget", la commande go recherche src/pkg/widget à l'intérieur de la racine Go, et ensuite - si le source du package n'est pas trouvé là-bas - elle recherche src/widget à l'intérieur de chaque espace de travail dans l'ordre.

(un "espace de travail" est une entrée de chemin dans votre GOPATH: cette variable peut référencer plusieurs chemins pour que vos 'src, bin, pkg' y soient)


(Réponse originale)

Vous devez également définir GOPATH sur ~/go, pas GOROOT, comme illustré dans "Comment écrire du code Go".

Le Go path est utilisé pour résoudre les déclarations d'import. Il est implémenté et documenté dans le package go/build.

La variable d'environnement GOPATH répertorie les endroits où chercher du code Go.
Sur Unix, la valeur est une chaîne séparée par des deux-points.
Sur Windows, la valeur est une chaîne séparée par des points-virgules.
Sur Plan 9, la valeur est une liste.

C'est différent de GOROOT:

Les distributions binaires Go supposent qu'elles seront installées dans /usr/local/go (ou c:\Go sous Windows), mais il est possible de les installer dans un emplacement différent.
Si vous le faites, vous devrez définir la variable d'environnement GOROOT sur ce répertoire lors de l'utilisation des outils Go.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X