2015-09-18 2 views
5

Jak uzyskać aktualny GOPATH z bloku kodu?Jak uzyskać aktualny GOPATH z kodu

runtime ma tylko GOROOT:

// GOROOT returns the root of the Go tree. 
// It uses the GOROOT environment variable, if set, 
// or else the root used during the Go build. 
func GOROOT() string { 
    s := gogetenv("GOROOT") 
    if s != "" { 
     return s 
    } 
    return defaultGoroot 
} 

mogłem zrobić funkcję, która ma GOROOT zastąpiony GOPATH, ale jest tam buildin do tego?

Odpowiedz

10

Zastosowanie os.Getenv

Od docs:

getenv pobiera wartość zmiennej środowiskowej o nazwie klucza . Zwraca wartość, która będzie pusta, jeśli zmienna nie jest obecna.

Przykład:

package main 

import (
    "fmt" 
    "os" 
    ) 

func main() { 
    fmt.Println(os.Getenv("GOPATH")) 
} 

Aktualizacja idź 1.8+

Go 1.8 posiada domyślną GOPATH eksportowany przez GO/Budowa:

package main 

import (
    "fmt" 
    "go/build" 
    "os" 
) 

func main() { 
    gopath := os.Getenv("GOPATH") 
    if gopath == "" { 
     gopath = build.Default.GOPATH 
    } 
    fmt.Println(gopath) 
} 
+4

W wersji 1.8 parametr GOPATH env var jest opcjonalny. Co jeśli użytkownik go nie ma? Czy istnieje sposób na uzyskanie domyślnego? Wydaje mi się, że środowisko uruchomieniowe go powinno mieć sposób na uzyskanie gopatha, pozwalając, aby sam Go sobie z tym poradził. – tothemario

+0

@tothemario Zamieściłem odpowiedź, w jaki sposób można uzyskać prawidłowy "GOPATH" od wersji Go 1.8. Zgadzam się jednak, że w idealnym przypadku środowisko wykonawcze powinno zapewniać sposób uzyskiwania "GOPATH" użytkownika. – tmh

+1

@tothemario zaktualizowano odpowiedź używając kodu z domyślnej implementacji ścieżki Go 1.8. – codefreak

1

Ponieważ Go 1.8 istnieje a default GOPATH:

Zmienna środowiskowa GOPATH określa położenie obszaru roboczego . Domyślnie jest to katalog o nazwie idź do twojego domowego katalogu , więc $HOME/go na Unix, $home/go na Plan 9 i %USERPROFILE%\go (zwykle C:\Users\YourName\go) w systemie Windows.

Oznacza to, że zmienna środowiskowa GOPATH niekoniecznie jest ustawiona na coś szczególnego.

Można nadal używać os.Getenv aby uzyskać wartość, ale w przypadku, gdy nie jest ustawiony trzeba się upewnić, że używasz domyślnej wartości PLATTFORM specyficzne zamiast, na przykład za pomocą mitchellh/go-homedir:

package main 

import (
     "fmt" 
     "log" 
     "os" 

     "github.com/mitchellh/go-homedir" 
) 

func main() { 
     p, err := gopath() 
     if err != nil { 
       log.Fatalf("Error finding GOPATH: %v", err) 
     } 

     fmt.Println(p) 
} 

func gopath() (string, error) { 
     s := os.Getenv("GOPATH") 
     if s != "" { 
       return s, nil 
     } 
     return homedir.Expand("~/go") 
} 
+0

To trochę przesady. Możemy użyć kodu z kodu źródłowego Go, aby uzyskać domyślną ścieżkę dostępu. Zobacz https://github.com/golang/go/blob/go1.8/src/go/build/build.go#L260-L277 – codefreak

+0

@codefreak Istnieją na pewno prostsze sposoby i twoja odpowiedź jest również ważna. To, co podoba mi się w 'go-homedir', to to, że w razie wątpliwości próbuje różnych sposobów odnalezienia katalogu domowego, a jeśli wszystko zawiedzie, to zwraca błąd. Tak więc użytkownicy tego kodu mogą zwrócić znaczący komunikat o błędzie. Jeśli po prostu zwrócisz pusty ciąg, użytkownicy muszą sprawdzić, czy jest pusty. Jeśli zignorują to, może to prowadzić do nieoczekiwanego zachowania lub dziwnych błędów w niektórych skrajnych przypadkach. – tmh

+0

Punktem zapytania jest znalezienie GOPATH, a nie domu reż. go-homedir świetnie nadaje się do odnajdywania w domu reż. Ale jeśli Go sama używa domyślnej funkcji GOPATH, to o co chodzi w dbaniu o skrajne przypadki, o których nie wspomina sam kod budujący Go. W każdym razie pozwólmy użytkownikom decydować, co im się najbardziej podoba :) – codefreak

4

Powinieneś użyć pakietu go/build.

package main 

import (
    "fmt" 
    "go/build" 
) 

func main() { 
    fmt.Println(build.Default.GOPATH) 
} 
0

Dzisiaj zajmowałem się tym czymś, nad czym pracuję i było to bardziej denerwujące, niż się spodziewałem. W końcu wydawało mi się, że to działa dla mnie w różnych testach, które zrobiłem (nie "rygorystycznych" testów).

goPath := strings.Split(os.Getenv("GOPATH"), string(os.PathListSeparator)) 
if len(goPath) == 0 { 
    goPath = append(goPath, build.Default.GOPATH) 
} else if goPath[0] == "" { 
    goPath[0] = build.Default.GOPATH 
} 

Zauważ, że zdecydowałem się użyć tylko 1st ścieżkę jeśli wiele ścieżek są notowane na GOPATH, jak podejrzewam, niewiele będzie miał więcej niż 1 ścieżka na liście, a pierwszy będzie gdzie go get stawia źródła (chyba). Ten kod nie uwzględnia również, czy ścieżki są poprawne, czy nie.

Zauważ również, że aby zbudować ścieżkę pliku po uzyskaniu GOPATH, musiałem użyć path/filepath.Join(), a nie path.Join(). Ten pierwszy użyje \ na Windows, jeśli pierwszy argument zawiera \, i/dla innych. Chociaż Windows może akceptować/dla ścieżek pozornie, wszystkie moje zmienne środowiskowe PATH i GOPATH są zapisane z normalnymi \ z okien. path.Join() użyte /, tworząc niepoprawną ścieżkę.