wake-up-neo.com

Automatisches Definieren von GOPATH pro Projekt

Für jedes Projekt, das ich erstelle, muss ich export GOPATH={path_to_project} jedes Mal tun, wenn ich in das Projektverzeichnis cd gehe. Es muss einen einfacheren Weg geben. Gibt es keine Möglichkeit, eine .bashrc- oder .bash_profile-Datei für ein bestimmtes Verzeichnis zu erstellen, um den GOPATH für dieses Projekt zu definieren?

Zum Beispiel habe ich zwei Go-Projekte A und B. Wenn ich ein einzelnes GOPATH habe, das beim Wechsel zwischen Projekten nicht neu definiert wird, werden die Binärdateien für beide Projekte an derselben Stelle gespeichert. Noch wichtiger ist, dass Binärdateien für Bibliotheken von Drittanbietern an derselben Stelle gespeichert werden. Ich habe also keine Möglichkeit, mehrere Versionen derselben Bibliothek pro Projekt zu verwalten.

Wenn ich GOPATH jedoch pro Projekt definieren kann, sind alle Binärdateien und Fremdbibliotheken von einem Projekt abhängig. Dies scheint die übliche Art der Paketverwaltung in den meisten anderen Sprachumgebungen zu sein (Ruby Rbenv, Python Vertiualenv usw.).

23
Daniel Nill

(F2 2018: Beachten Sie, dass mit dem Projekt vgo (jetzt "module")GOPATH zugunsten eines projektbasierten Workflows möglicherweise als veraltet eingestuft wird. basierend GOPATH Ich schlug vor zwei Jahren vor)

Mit Go 1.11 (August 2018) kann GOPATH optional mit Modulen sein.


Sie haben eine ähnliche Idee in Verwalten Sie mehrere GOPATH-Verzeichnisse mit Leichtigkeit , von Herbert Fischer (hgfischer) für eine Linux/Unix-Umgebung (Basis: die Frage bereits in den Kommentaren oben erwähnt):

Fügen Sie einfach das folgende Snippet in Ihren ~/.bashrc (oder ~/.bash_profile) ein und laden Sie Ihre Shell-Umgebung mit source ~/.bashrc neu.
Mit diesem Snippet wird eine Shell-Funktion erstellt, die den eingebauten Befehl cd mit einem benutzerdefinierten Befehl überschreibt, der das eingegebene Verzeichnis und jedes andere darüber nach einer Datei mit dem Namen .gopath durchsucht.

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

Jetzt müssen Sie nur noch eine .gopath-Datei in jedem gewünschten Verzeichnis als GOPATH erstellen. Bei jedem Aufruf dieses Verzeichnisses setzt die neu definierte cd-Funktion die GOPATH Ihrer aktuellen Umgebung auf dieses Verzeichnis.


Update 2017: Wenn Sie Ihre Umgebung nicht ändern möchten, können Sie dennoch eine GOPATH pro Projekt verwenden. Öffnen Sie dazu den src-Ordner dieses Projekts in Visual Studio Code ( vscode , einer Plattform mit mehreren Plattformen IDE), kombiniert mit der Erweiterung " für Visual Studio Code ".

In dieser IDE können Sie:

  • behalten Sie Ihre globale Eindeutigkeit GOPATH in einer Einstellung mit dem Namen go.toolsGopath.
  • schlagen Sie Ihre aktuelle GOPATH mit einer Einstellung namens go.inferGopath ab.

vscode user settings

Auf diese Weise installiert VSCode eine Sammlung von Tools in Ihrer globalen GOPATH (die Sie auch außerhalb von VSCode verwenden können).
Siehe " Go-Tools, von denen die Go-Erweiterung abhängt ": godep, golint, guru, godoc, ...

Und dennoch ist Ihre GOPATH für Ihr Projekt der übergeordnete Ordner von src:

local GOPATH

Das funktioniert, wenn Sie Ihr Projekt von der IDE aus kompilieren/installieren.
Wenn Sie dies über die Befehlszeile ausführen möchten, gilt die ursprüngliche Antwort oben.

19
VonC

Sie können ein Tool wie autoenv verwenden, um ein Skript einzurichten, das automatisch ausgeführt wird, wenn Sie in ein bestimmtes Verzeichnis cd wechseln.

Für Ihre Zwecke könnte eine /happy/go/path/yay/.env-Beispieldatei folgendermaßen aussehen:

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

Ich würde ein Skript schreiben, das den richtigen GOPATH aus dem aktuellen Verzeichnis ableiten kann, und dann den Befehl go als Alias ​​bezeichnen, um dieses Skript zuerst aufzurufen. Zum Beispiel eine sehr einfache Implementierung:

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

pwd

Und dann in .bash_aliases (oder wo immer Sie Ihre Aliasnamen aufbewahren):

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

Dadurch wird GOPATH auf beliebige infer-gopath.sh-Ausgaben gesetzt, die nur für den Aufruf des go-Befehls verwendet werden, so dass es keine dauerhaften Auswirkungen auf Ihre Shell hat.

5
joshlf

Mein Eindruck ist, dass das go-Tool aktiv davon abhält, "mehrere Versionen derselben Bibliothek pro Projekt zu verwalten", aus genau dem Grund, dass die Erfahrung gezeigt hat, dass diese Strategie nicht für große Codebasen (wie die von Google) funktioniert. Es wurde viel über die Paketversionierung von Golang-Nüssen diskutiert: ( Suche in der Liste ), und es scheint, dass die Diskussion noch offen ist, wie von Ian Lance Taylor in diesem Juni angegeben 6, 2013 interview (Suche nach dem Wort "Versionierung").

Das go-Paketsystem ist so konzipiert, dass jedes Projekt eine eigene Verzeichnisstruktur haben kann. Die einzige Einschränkung ist, dass sie alle untergeordneten (einigen) Verzeichnissen in GOPATH sein müssen. Dies hat den Vorteil, dass es gut mit Versionskontrollsystemen interagiert, solange der VCS-Master immer baut. In dem oben genannten Blog-Interview schlägt ILT vor:

Wir machen intern eine Momentaufnahme des importierten Codes und aktualisieren diese von Zeit zu Zeit. Auf diese Weise bricht unsere Codebasis nicht unerwartet, wenn sich die API ändert.

Ersetzen Sie "meine anderen Bibliotheken" durch "den importierten Code". Dies scheint eine Möglichkeit zu sein. Sie könnten zwei go-Verzeichnisse haben, Produktion und Entwicklung. Für die Entwicklung können Sie das Entwicklungsverzeichnis an erster Stelle in den Pfad einfügen, sodass Binärdateien und Bibliotheken für die Entwicklung die Produktionsverzeichnisse nicht verschmutzen. Ich weiß nicht, ob das ausreicht.

Wenn Sie wirklich für jedes Projekt eine eigene GOPATH haben möchten, würde ich Folgendes vorschlagen:

1) Lassen Sie jedes Projekt GOPATH auf ein Verzeichnis mit dem Namen go (oder ein ähnliches) enden.

2) Deduzieren Sie die GOPATH mit der folgenden Shell-Funktion (fast völlig ungetestet):

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

Dann können Sie gopath anstelle von go verwenden, sofern sich Ihr aktuelles Arbeitsverzeichnis irgendwo im Projekt-Repository befindet. (Zu den weiterentwickelten Möglichkeiten gehört die Verwendung des explizit angegebenen Projektpfads, um gegebenenfalls GOPATH abzuleiten.)

3
rici

Ich weiß, dass dies nicht sehr klug ist, aber ich finde, wenn ich einfach in das Basisverzeichnis des go-Projekts gehe, in dem ich die Ordner src, pkg und bin habe, kann ich einfach Folgendes eingeben: 

export GOPATH=$(pwd)

und das ist alles gut!

2
user2855262

Ich kann nicht kommentieren, aber um die Antwort von @joshlf ::: aufzubauen:

alias ​​go durch Voranstellen der GOPATH - Für meine Methode müssen Sie keine zusätzliche Datei erstellen/erstellen:

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

prost

1
lukeed

Ich bin ein Golang-Neuling, aber der beste Weg, dies zu tun, wäre wahrscheinlich, ein Shell-Skript in jedem Ihrer Projekte zu erstellen, Ihr Projekt zu erstellen/auszuführen und dieses Skript in Ihre Projektwurzel zu setzen :)

#!/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

dieses Skript sollte funktionieren, auch wenn Sie es aus einem Verzeichnis ausführen, das nicht das Projektstammverzeichnis ist.

0
Alexander Mills

Ich mag den Mut von the gopath () antworte oben , aber ich mag es nicht (a), dass die Variable GOPATH nur für den Befehl go gesetzt ist (ich verwende es in vim Plugins usw.), noch mag ich es ( b) Denken Sie daran, gopath anstelle von go einzugeben :)

Folgendes habe ich schließlich zu meinem ~/.bash_profile hinzugefügt:

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

(Ich habe das oben auch mit einer kleinen zusätzlichen Diskussion der Anforderungen aufgeschrieben in diesem Blogbeitrag )

0
el_bhs