web-dev-qa-db-fra.com

Golang comment importer des paquets locaux sans gopath?

J'ai utilisé GOPATH mais pour le problème actuel, je n'y suis pas obligé. Je veux pouvoir créer des packages spécifiques à un projet:

myproject/
├── binary1.go
├── binary2.go
├── package1.go
└── package2.go

J'ai essayé plusieurs façons, mais comment puis-je obtenir que package1.go fonctionne dans le binary1.go ou le binary2.go et ainsi de suite?

Par exemple; Je veux pouvoir utiliser import "package1", puis pouvoir exécuter go build binary1.go et tout fonctionne correctement, sans que le paquet ne puisse être trouvé sur GOROOT ou GOPATH. La raison pour laquelle j'ai besoin de ce type de fonctionnalité est destinée aux projets à grande échelle; Je ne veux pas avoir à faire référence à plusieurs autres packages ou à les conserver dans un seul fichier volumineux.

134
user1529891

Allez résumé de la gestion des dépendances:

  • vgo si votre version go est: x >= go 1.11
  • dep ou vendor si votre version go est: go 1.6 >= x < go 1.11
  • Manuellement si votre version go est: x < go 1.6

Edit 3: Go 1.11 a une fonction vgo qui va remplacerdep.

Pour utiliser vgo, consultez la documentation de Modules . TLDR ci-dessous:

export GO111MODULE=on
go mod init
go mod vendor # if you have vendor/ folder, will automatically integrate
go build

Cette méthode crée un fichier appelé go.mod dans votre répertoire de projets. Vous pouvez ensuite construire votre projet avec go build. Si GO111MODULE=auto est défini, votre projet ne peut pas être dans $GOPATH.


Edit 2: La méthode de vente est toujours valide et fonctionne sans problème. vendor est en grande partie un processus manuel, à cause de cela dep et vgo ont été créés.


Edit 1: Bien que mon ancienne méthode fonctionne, ce n’est plus la manière "correcte" de le faire. Vous devriez utiliser les fonctionnalités du fournisseur , vgo ou dep (pour l'instant) activées par défaut dans Go 1.6; voir . Vous ajoutez essentiellement vos packages "externes" ou "dépendants" dans un répertoire vendor; lors de la compilation, le compilateur utilisera d'abord ces paquets.


A trouvé. J'ai pu importer un paquet local avec GOPATH en créant un sous-dossier de package1, puis en important avec import "./package1" dans binary1.go et binary2.go comme ceci:

binary1.go

...
import (
        "./package1"
      )
...

Donc, ma structure de répertoire actuelle ressemble à ceci:

myproject/
├── binary1.go
├── binary2.go
├── package1/
│   └── package1.go
└── package2.go

Je devrais également noter que les chemins relatifs (au moins dans go 1.5) fonctionnent également; par exemple:

import "../packageX"
153
user1529891

Il n'y a pas de "paquet local". L'organisation des packages sur un disque est orthogonale à toute relation parent/enfant des packages. La seule hiérarchie réelle formée par les packages est l'arbre de dépendance, qui dans le cas général ne reflète pas l'arborescence de répertoires.

Juste utiliser

import "myproject/packageN"

et ne combattez pas le système de compilation sans bonne raison. Enregistrer une douzaine de caractères par importation dans un programme non trivial n’est pas une bonne raison, car, par exemple, les projets avec des chemins d’importation relatifs ne sont pas contrôlables.

Le concept de chemins d'importation a des propriétés importantes:

  • Les chemins d'importation peuvent être globalement uniques.
  • En conjonction avec GOPATH, le chemin d'importation peut être traduit sans ambiguïté en chemin de répertoire.
  • Tout chemin de répertoire sous GOPATH peut être traduit sans ambiguïté en un chemin d'importation.

Tout ce qui précède est ruiné par l’utilisation de chemins d’importation relatifs. Ne fais pas ça.

PS: Il y a peu d’endroits dans l’ancien code dans les tests du compilateur Go qui utilisent des importations relatives. ATM, c’est la seule raison pour laquelle les importations relatives sont prises en charge.

65
zzzz

Peut-être que vous essayez de modulariser votre paquet. Je suppose que package1 et package2 font, en quelque sorte, partie du même paquet, mais pour des raisons de lisibilité, vous les divisez en plusieurs fichiers.

Si le cas précédent était le vôtre, vous pouvez utiliser le même nom de package dans ces fichiers multiples et ce sera comme s'il y avait le même fichier.

Ceci est un exemple:

add.go

package math

func add(n1, n2 int) int {
   return n1 + n2
}

soustraire.go

package math

func subtract(n1, n2 int) int {
    return n1 - n2
}

donothing.go

package math

func donothing(n1, n2 int) int {
    s := add(n1, n2)
    s = subtract(n1, n2)
    return s
}

Je ne suis pas un expert de Go et ceci est mon premier message dans StackOveflow. Par conséquent, si vous avez des conseils, ils seront bien reçus.

41
Juan Jose Tugores

J'ai un problème similaire et la solution que j'utilise actuellement utilise les modules Go 1.11. J'ai la structure suivante

- projects
  - go.mod
  - go.sum
  - project1
    - main.go
  - project2
    - main.go
  - package1
    - lib.go
  - package2
    - lib.go

Et je peux importer package1 et package2 à partir de project1 et project2 en utilisant

import (
    "projects/package1"
    "projects/package2"
)

Après avoir exécuté go mod init projects. Je peux utiliser go build à partir des répertoires project1 et project2 ou à go build -o project1/exe project1/*.go à partir du répertoire de projets.

L'inconvénient de cette méthode est que tous vos projets partagent la même liste de dépendances dans go.mod. Je cherche toujours une solution à ce problème, mais il semble que cela puisse être fondamental.

14
Mad Wombat

Pour ajouter un package "local" à votre projet, ajoutez un dossier (par exemple "package_name"). Et mettez vos fichiers d'implémentation dans ce dossier.

src/github.com/GithubUser/myproject/
 ├── main.go
 └───package_name
       └── whatever_name1.go
       └── whatever_name2.go

Dans votre package main procédez comme suit:

import "github.com/GithubUser/myproject/package_name"

package_name est le nom du dossier et il doit correspondre au nom du paquet utilisé dans les fichiers nom_ieux1.go et nom_ nom2.go. En d'autres termes, tous les fichiers avec un sous-répertoire doivent être du même paquet.

Vous pouvez également imbriquer davantage de sous-répertoires tant que vous spécifiez le chemin d'accès complet au dossier parent dans l'importation.

5
Homan