web-dev-qa-db-fra.com

Définir automatiquement GOPATH projet par projet

Pour chaque projet que je crée, je dois faire export GOPATH={path_to_project} chaque fois que je cd dans le répertoire du projet. Il doit y avoir un moyen plus facile. N'y a-t-il pas moyen de créer un fichier .bashrc ou .bash_profile pour un répertoire donné afin de définir GOPATH pour ce projet?

Par exemple, j'ai deux projets A et B. Si j'ai un GOPATH singulier qui n'est pas redéfini lorsque je passe d'un projet à un autre, les fichiers binaires des deux projets seront stockés au même endroit. Plus important encore, les fichiers binaires des bibliothèques tierces seront stockés au même endroit. Par conséquent, je n'ai aucun moyen de gérer plusieurs versions de la même bibliothèque pour chaque projet.

Cependant, si je suis en mesure de définir GOPATH pour chaque projet, tous les binaires et toutes les bibliothèques tierces dépendent du projet. Cela semble être la manière habituelle de gérer la gestion des paquets dans la plupart des autres environnements de langage (Ruby rbenv, python vertiualenv, etc.)

23
Daniel Nill

(T2 2018: Notez qu'avec le projet vgo (maintenant "module"), le projet , GOPATH pourrait finir par être obsolète au profit d'un flux de travail basé sur un projet. Cela éviterait la GOPATH basée sur un projet manuel Je proposais ci-dessous, il y a deux ans)

Avec Go 1.11 (août 2018), GOPATH peut être facultatif, avec les modules .


Vous avez une idée similaire exprimée dans Gérer plusieurs répertoires GOPATH avec facilité , par Herbert Fischer (hgfischer) , pour un environnement Linux/Unix (base sur la question mentionne déjà dans les commentaires ci-dessus):

Incluez simplement l'extrait de code suivant dans votre ~/.bashrc (ou ~/.bash_profile) et rechargez votre environnement Shell avec source ~/.bashrc.
Cet extrait créera une fonction Shell qui remplacera la commande intégrée cd par une commande personnalisée qui analysera le répertoire entré, ainsi que tous les autres, pour un fichier nommé .gopath.

cd () {
    builtin cd "$@"
    cdir=$PWD
    while [ "$cdir" != "/" ]; do
        if [ -e "$cdir/.gopath" ]; then
            export GOPATH=$cdir
            break
        fi
        cdir=$(dirname "$cdir")
    done
}

Maintenant, il vous suffit de créer un fichier .gopath dans chaque répertoire de votre choix comme GOPATH et chaque fois que vous entrez dans ce répertoire, la fonction redéfinie cd définira la GOPATH de votre environnement actuel sur ce répertoire.


Mise à jour 2017: si vous ne souhaitez pas modifier votre environnement, vous pouvez toujours utiliser une GOPATH par projet, en ouvrant le dossier src de ce projet dans le code Visual Studio ( vscode , qui est un IDE multi-plateforme). , combiné avec l’extension " Go for Visual Studio Code ".

Dans cet IDE, vous pouvez:

  • conservez votre GOPATH globale unique dans un paramètre appelé go.toolsGopath.
  • déduire votre GOPATH actuelle avec un paramètre appelé go.inferGopath

 vscode user settings

De cette façon, VSCode installera une collection d’outils dans votre GOPATH globale (que vous pourrez également utiliser en dehors de VSCode).
Voir " Outils Go dont dépend l’extension Go ": godep, golint, guru, godoc, ...

Et pourtant, votre GOPATH pour votre projet sera le dossier parent de src:

 local GOPATH

Cela fonctionne lorsque vous compilez/installez votre projet à partir de l'EDI.
Si vous voulez le faire depuis la ligne de commande, la réponse originale ci-dessus s'appliquerait toujours.

19
VonC

Vous pouvez utiliser un outil tel que autoenv pour configurer un script qui s’exécute automatiquement lorsque vous cd dans un répertoire particulier.

Pour vos besoins, un exemple de fichier /happy/go/path/yay/.env pourrait ressembler à ceci:

export GOPATH="/happy/go/path/yay"
export PATH="$GOPATH/bin:$PATH"
9
Brent

Je voudrais écrire un script qui peut déduire le bon GOPATH du répertoire actuel, puis aliaser la commande go pour appeler d’abord ce script. Par exemple, une implémentation très simple:

#!/bin/bash
# infer-gopath.sh

pwd

Et ensuite, dans .bash_aliases (ou où que vous gardiez vos alias):

alias go='GOPATH=$(infer-gopath.sh) go'

Ceci définit GOPATH sur les sorties infer-gopath.sh uniquement pour l'invocation de la commande go, de sorte que cela n'aura aucun effet durable sur votre shell.

5
joshlf

Mon impression est que l'outil go décourage activement le "maintien de plusieurs versions de la même bibliothèque sur une base par projet" pour la raison précise que l'expérience a montré que cette stratégie ne fonctionne pas sur des bases de code volumineuses (telles que celles de Google). Il y a eu beaucoup de discussions sur la gestion des versions de paquets sur les golang-nuts: ( recherchez dans la liste ), et il semble que la discussion soit toujours ouverte, comme indiqué par Ian Lance Taylor Le 6 juin 2013 interview (recherche du mot "versioning").

Le système de packaging go est conçu pour permettre à chaque projet d’avoir sa propre structure de répertoires; la seule restriction est qu'ils doivent tous être enfants de (certains) répertoires dans GOPATH. Cela présente l'avantage de bien interagir avec les systèmes de contrôle de version, tant que le maître VCS est toujours construit. Dans l'interview de blog référencée ci-dessus, ILT suggère:

Ce que nous faisons en interne est de prendre un instantané du code importé et de le mettre à jour de temps à autre. De cette façon, notre base de code ne sera pas interrompue de manière inattendue si l'API change.

Substituer "le code importé" à "mes autres bibliothèques", cela semble être une possibilité; vous pouvez avoir deux répertoires go, production et développement; pour le développement, vous pouvez placer le répertoire de développement en premier dans le chemin afin que les fichiers binaires et les bibliothèques de développement ne polluent pas les répertoires de production. Je ne sais pas si cela suffit.

Si vous voulez vraiment avoir une GOPATH distincte pour chaque projet, je vous suggère ce qui suit:

1) Faites en sorte que la GOPATH de chaque projet se termine dans un répertoire nommé go (ou quelque chose du genre)

2) Déduisez la GOPATH en utilisant quelque chose comme la fonction Shell suivante (presque totalement non testée):

gopath() {
  GOPATH="$(
    ( while [[ $PWD != / && $(basename $PWD) != go ]]; do
        cd ..
      done
      if [[ $PWD == / ]]; then
        echo $GOPATH
      else
        echo $PWD
      fi
    ))" go "$@"
}

Ensuite, vous pouvez utiliser gopath au lieu de go tant que votre répertoire de travail actuel se trouve quelque part dans le référentiel du projet. (Des possibilités plus sophistiquées peuvent inclure l’utilisation du chemin de projet explicitement fourni, le cas échéant, pour déduire GOPATH.)

3
rici

Je sais que ce n’est pas très intelligent, mais je trouve que si je vais simplement dans le répertoire de base du projet go où j’ai les dossiers src, pkg et bin, je peux simplement taper: 

export GOPATH=$(pwd)

et c'est tout bon!

2
user2855262

Je ne peux pas commenter, mais pour reprendre la réponse de @joshlf :::

alias go en préfixant la GOPATH - ma méthode n'exige pas que vous traitiez/créiez un fichier supplémentaire:

alias go='GOPATH=$(echo $(pwd)) go'

à votre santé

1
lukeed

Je suis un newb Golang, mais la meilleure façon de le faire serait probablement de créer un script Shell dans chacun de vos projets, de construire/exécuter votre projet et de placer ce script à la racine de votre projet :)

#!/usr/bin/env bash

// get absolute path to the directory which contains this script
PROJECT_DIR=$(cd $(dirname $0) && pwd)

// set GOPATH as you wish, then run go build
GOPATH=${GOPATH}:${PROJECT_DIR} && cd ${PROJECT_DIR} && go build

ce script devrait fonctionner même si vous l'exécutez à partir d'un répertoire qui n'est pas la racine du projet.

0
Alexander Mills

J'aime les tripes de la réponse de gopath () ci-dessus , mais je n'aime pas (a) le fait que GOPATH soit défini uniquement pour la commande go (je l'utilise dans les plugins vim, etc.), et je n'aime pas non plus ( b) ne pas oublier de taper gopath au lieu de go :)

C'est ce que j'ai finalement ajouté à mon ~/.bash_profile:

export GOPATH="... a default path ..."
function cd() {
  builtin cd $@ &&
  export GOPATH="$(
    ( while [[ $PWD != / && $(basename $PWD) != go ]]; do
        cd ..
      done
      if [[ $PWD == / ]]; then
        echo $GOPATH
      else
        echo $PWD
      fi
    ))"
}

(J'ai aussi écrit ce qui précède avec une petite discussion supplémentaire sur les exigences dans cet article de blog )

0
el_bhs