Reputation: 16029
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?
Upvotes: 23
Views: 26605
Reputation: 7141
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)
}
Upvotes: 36
Reputation: 5309
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.
Upvotes: 1
Reputation: 140
You should use go/build package.
package main
import (
"fmt"
"go/build"
)
func main() {
fmt.Println(build.Default.GOPATH)
}
Upvotes: 14
Reputation: 1445
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
(usuallyC:\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")
}
Upvotes: 0