Je ne trouve pas de moyen de factoriser du code à partir de main.go
dans un package local lors de l'utilisation de modules Go (version go> = 1.11) en dehors de $GOPATH
.
Je n'importe pas de dépendances externes qui doivent être incluses dans go.mod
, J'essaie juste d'organiser localement le code source de ce module Go.
Le fichier main.go
:
package main
// this import does not work
import "./stuff"
func main() {
stuff.PrintBaz()
}
Le fichier ./stuff/bar.go
(faisant semblant d'être un package local):
package stuff
import "log"
type Bar struct {
Baz int
}
func PrintBaz() {
baz := Bar{42}
log.Printf("Bar struct: %v", baz)
}
Le fichier go.mod
(commande go mod init foo
):
module foo
go 1.12
Lors de l'exécution de go run main.go
:
import "./stuff"
, alors je vois build command-line-arguments: cannot find module for path _/home/<PATH_TO>/fooprj/stuff
.import "stuff"
, alors je vois build command-line-arguments: cannot load stuff: cannot find module providing package stuff
.import stuff "./stuff"
avec un alias de package, puis je revois: build command-line-arguments: cannot find module for path _/home/<PATH_TO>/fooprj/stuff
.Je ne trouve pas de moyen de faire fonctionner les packages locaux avec les modules go.
go.mod
)?Vous devez d'abord choisir un nom pour votre projet et l'écrire dans le fichier go.mod. Ce nom appartient au répertoire racine du projet. Chaque nouveau package que vous créez doit se trouver dans son propre sous-répertoire et son nom doit correspondre au nom du répertoire.
go.mod:
module myprojectname
ou (manière préférée, voir @ typique182 réponse ci-dessous pour plus de détails)
module github.com/myname/myproject
Importez ensuite les packages de votre projet comme:
import myprojectname/stuff
ou
import github.com/myname/myproject/stuff
Les fichiers du package stuff
doivent se trouver dans le répertoire stuff
du projet. Vous nommez ces fichiers comme vous le souhaitez.
Il est également possible de créer une structure de projet plus profonde. Par exemple, vous avez décidé de séparer les fichiers de code source des autres (comme les configurations d'applications, les fichiers docker, les fichiers statiques, etc.). Déplaçons le répertoire stuff
dans pkg
, chaque fichier go dans pkg/stuff
ont toujours stuff
nom du package. Pour importer un paquet de trucs, écrivez simplement:
import myprojectname/pkg/stuff
Rien ne vous empêche de créer plus de niveaux dans la hiérarchie comme github.com/myuser/myproject/pkg/db/provider/postgresql
, où:
github.com/myuser/myproject
- nom du projet.postgresql
- nom du package.pkg/db/provider/postgresql
- chemin vers le package par rapport à la racine du projet.Vous pouvez en savoir plus sur les modules go ici: https://github.com/golang/go/wiki/Modules
Consultez ce référentiel pour obtenir des informations utiles sur les différents modèles utilisés dans l'organisation de projet: https://github.com/golang-standards/project-layout Si vous allez dans le répertoire pkg
vous va découvrir quels projets open source utilisent le répertoire pkg
dans leur structure.
L'approche la plus courante et la plus simple est:
go.mod
par référentiel, etgo.mod
fichier dans la racine du référentiel, etmodule
dans le go.mod
me.io/mymod
plutôt que d'utiliser un chemin d'importation basé sur l'hôte VCS, vous utiliseriez le chemin d'importation personnalisé au lieu du nom du référentiel dans votre go.mod
).Par exemple, si votre dépôt est github.com/my/repo
, vous placez un seul go.mod
dans la racine du référentiel, la première ligne indiquant module github.com/my/repo
. Cela peut être créé en cd
'à la racine du référentiel et en exécutant go mod init github.com/my/repo
.
Suivre cela vous aide à rester sur la bonne voie avec les modules, et cela évite plusieurs subtilités.
Russ Cox a commenté dans # 26664 :
Pour tous, sauf les utilisateurs expérimentés, vous souhaiterez probablement adopter la convention habituelle selon laquelle un dépôt = un module. Il est important pour l'évolution à long terme des options de stockage de code qu'un dépôt peut contienne plusieurs modules, mais ce n'est certainement pas quelque chose que vous voulez faire par défaut.
Il y a beaucoup plus sur les référentiels multi-modules dans la "Référentiels multi-modules" FAQ section sur le wiki des modules. Ces 6 ou plus FAQ dans cette section devraient être lues dans leur intégralité par quiconque envisage de déroger à la recommandation ci-dessus.
Une fois que vous avez configuré votre go.mod
, vous pouvez organiser vos packages dans des répertoires comme bon vous semble dans des répertoires sous le répertoire contenant le go.mod
, ainsi que dans le répertoire avec le go.mod
. Trois bons articles sur la façon d'organiser votre code dans des packages:
Ces articles sont des classiques qui sont antérieurs à l'introduction des modules, mais les philosophies qu'ils contiennent s'appliquent toujours à la façon d'organiser vos packages dans un module.
Lorsque vous importez un autre package avec des modules, vous utilisez toujours le chemin complet, y compris le chemin du module. Cela est vrai même lors de l'importation d'un autre package dans le même module. Par exemple, si un module a déclaré son identité dans son go.mod
comme module github.com/my/repo
, et vous aviez cette organisation:
repo/
├── go.mod <<<<< Note go.mod is located in repo root
├── pkg1
│ └── pkg1.go
└── pkg2
└── pkg1.go
Ensuite pkg1
importerait son package homologue en tant que import "github.com/my/repo/pkg2"
. Notez que vous ne pouvez pas utiliser des chemins d'importation relatifs comme import "../pkg2"
ou import "./subpkg"
. (Cela fait partie de ce que OP a frappé ci-dessus avec import "./stuff"
).
Un module Go est une collection de packages Go associés qui sont versionnés ensemble comme une seule unité. Les modules enregistrent des exigences de dépendance précises et créent des versions reproductibles.
Résumé de la relation entre les référentiels, les modules et les packages:
package foo
déclaration.import "github.com/my/repo/pkg1"
. Le chemin d'importation commence toujours par le chemin de module de ce package, que ce package se trouve dans le même module ou dans un module différent.