How to get current GOPATH from code

匿名 (未验证) 提交于 2019-12-03 00:46:02

问题:

How do I get the current GOPATH from a block of code?

runtime only has 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 } 

I could make a function that has GOROOT replaced with GOPATH, but is there a buildin for this?

回答1:

Use os.Getenv

From docs:

Getenv retrieves the value of the environment variable named by the key. It returns the value, which will be empty if the variable is not present.

Example:

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

Update for Go 1.8+

Go 1.8 has default GOPATH exported via go/build:

package main  import (     "fmt"     "go/build"     "os" )  func main() {     gopath := os.Getenv("GOPATH")     if gopath == "" {         gopath = build.Default.GOPATH     }     fmt.Println(gopath) } 


回答2:

You should use go/build package.

package main  import (     "fmt"     "go/build" )  func main() {     fmt.Println(build.Default.GOPATH) } 


回答3:

Since Go 1.8, there is a default GOPATH:

The GOPATH environment variable specifies the location of your workspace. It defaults to a directory named go inside your home directory, so $HOME/go on Unix, $home/go on Plan 9, and %USERPROFILE%\go (usually C:\Users\YourName\go) on Windows.

This means the GOPATH environment variable is not necessarily set to anything in particular.

You can still use os.Getenv to get the value, but in case it is not set you need to make sure that you use the the plattform-specific default value instead, for example using 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") } 


回答4:

I was messing with this today for something I am working on, and it was more annoying than I'd have expected. In the end, this seemed to work for me in the various tests I did on it (not 'rigorous' tests).

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 } 

Note that I decided to use only the 1st path if multiple paths are listed on GOPATH, as I suspect few will have more than 1 path listed, and the first would be where go get puts the source (I guess). This code also does not account for if the paths are valid or not.

Also note that to build a file path after getting the GOPATH, I had to use path/filepath.Join() not path.Join(). The former will use \ on windows if the first arg contains \, and / for others. Although windows can accept / for paths apparently, all of my PATH and GOPATH-like environmental variables are written with the normal \ of windows. path.Join() used /, producing an invalid path.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!