2015-09-18 16 views
5

Come ottengo l'attuale GOPATH da un blocco di codice?Come ottenere GOPATH corrente dal codice

runtime Basta 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 
} 

ho potuto fare una funzione che ha GOROOT sostituito con GOPATH, ma c'è un buildin per questo?

risposta

10

Usa os.Getenv

Da docs:

getenv recupera il valore della variabile d'ambiente chiamata dal tasto . Restituisce il valore, che sarà vuoto se la variabile non è presente.

Esempio:

package main 

import (
    "fmt" 
    "os" 
    ) 

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

Aggiornamento per Go 1.8+

Go 1.8 ha GOPATH di default esportato tramite go/build:

package main 

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

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

In go 1.8, GOPATH env var è facoltativo. Cosa succede se l'utente non ce l'ha? C'è un modo per ottenere quello predefinito? Penso che il runtime di go dovrebbe avere un modo per ottenere il gopath, lasciando che Go stesso lo capisca per te. – tothemario

+0

@tothemario Ho postato una risposta su come è possibile ottenere il 'GOPATH' valido da Go 1.8. Tuttavia, sono d'accordo che idealmente il runtime dovrebbe fornire un modo per ottenere il 'GOPATH 'dell'utente. – tmh

+1

@tothemario ha aggiornato la risposta utilizzando il codice dall'implementazione predefinita del percorso go di Go 1.8. – codefreak

1

Dal Go 1.8, non v'è a default GOPATH:

La variabile di ambiente GOPATH specifica la posizione dell'area di lavoro . Il valore predefinito è una directory denominata andare nella directory di casa, quindi $HOME/go su Unix, $home/go su Plan 9 e %USERPROFILE%\go (in genere C:\Users\YourName\go) su Windows.

Ciò significa che la variabile di ambiente GOPATH non è necessariamente impostata su qualcosa in particolare.

È comunque possibile utilizzare os.Getenv per ottenere il valore, ma nel caso in cui non lo è impostato è necessario fare in modo di utilizzare il valore di default specifici Piattaforma, invece, ad esempio utilizzando 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

È un po 'eccessivo. Possiamo usare il codice dal codice sorgente di Go per ottenere il percorso di default. Vedi https://github.com/golang/go/blob/go1.8/src/go/build/build.go#L260-L277 – codefreak

+0

@codefreak Ci sono modi sicuramente più semplici e anche la tua risposta è valida. Quello che mi piace di 'go-homedir' è che, nel dubbio, cerca più modi di trovare la home directory, e se tutto fallisce, in realtà restituisce un errore. Quindi gli utenti di questo codice possono restituire un messaggio di errore significativo. Se si restituisce solo una stringa vuota, gli utenti devono controllare se è vuota. Se dovessero trascurarlo, ciò potrebbe portare a comportamenti imprevisti o strani errori in alcuni casi limite. – tmh

+0

Il punto interrogativo è trovare GOPATH, non la directory home. go-homedir è ottimo per trovare casa dir. Ma se Go stesso utilizza la funzione di default GOPATH, qual è il punto di prendersi cura dei casi limite che il codice di go go stesso non si prende cura di. Ad ogni modo lasciamo che gli utenti decidano cosa gli piace di più :) – codefreak

4

È necessario utilizzare il pacchetto go/build.

package main 

import (
    "fmt" 
    "go/build" 
) 

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

avrei dovuto vedermela con questo oggi per qualcosa che sto lavorando, ed è stato più fastidioso di quanto mi sarei aspettato. Alla fine, questo sembrava funzionare per me nei vari test che ho fatto su di esso (non test 'rigorosi').

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 
} 

Nota che ho deciso di utilizzare solo il 1 ° percorso se più percorsi sono elencati sul GOPATH, come sospetto poco avrà più di 1 percorso elencato, e il primo sarebbe dove go get mette la fonte (immagino). Questo codice non tiene conto se i percorsi sono validi o meno.

Si noti inoltre che per creare un percorso file dopo aver ottenuto GOPATH, ho dovuto utilizzare path/filepath.Join() non path.Join(). Il primo userà \ su windows se il primo argomento contiene \, e/per gli altri. Sebbene Windows possa accettare/per percorsi apparentemente, tutte le mie variabili ambientali PATH e GOPATH sono scritte con le normali \ di windows. path.Join() utilizzato /, che produce un percorso non valido.

Problemi correlati