Posted on October 1, 2012 by

Installing Go and $GOPATH

I’ve seen a lot of questions asked about $GOPATH and installing Go for the first time. $GOPATH is simply where Go will look for dependencies to build your application. Python has virtualenv. I don’t really know Java, but it has $JAVA_HOME. These are tools to setup your workspace for a project so the compiler knows where to find dependencies.

This is all that $GOPATH is. It specifies a workspace for your application. You can set a different $GOPATH for different applications to separate build dependencies. You can read about it on the Go website. That link is only referenced from the bottom of the Install instructions. Maybe a relocation would reduce the number of questions coming through.

When I install Go, I grab the binary download from the website. I create a ~/golang directory, and I untar into that directory.

mkdir ~/golang
cd ~/golang
wget https://storage.googleapis.com/golang/go1.3.1.linux-amd64.tar.gz
tar -xzf go1.3.1.linux-amd64.tar.gz

Now I setup my Go binary path. I do this using the $GOROOT and $PATH environment variables. In order to make these variables persist through logins/reboots/etc, I add the following lines to my ~/.bashrc file:

export GOROOT=$HOME/golang/go 
export PATH=$PATH:$GOROOT/bin

You can also copy/paste these lines into your command prompt to make these changes active right away. You should be able to run `go` now. But this is only half the setup. We need to setup $GOPATH. I think the best way to explain this is with an example:

rday@rday-laptop:~/golang$ mkdir packages1
rday@rday-laptop:~/golang$ export GOPATH=~/golang/packages1/
rday@rday-laptop:~/golang$ go get github.com/rday/web
rday@rday-laptop:~/golang$ ls packages1/src/github.com/
rday
rday@rday-laptop:~/golang$ mkdir packages2
rday@rday-laptop:~/golang$ export GOPATH=~/golang/packages2/
rday@rday-laptop:~/golang$ go get github.com/alphazero/Go-Redis
rday@rday-laptop:~/golang$ ls packages2/src/github.com/
alphazero
rday@rday-laptop:~/golang$

 

What just happened? Why did “go get” place those packages in different locations?

Go is storing our package dependencies in our $GOPATH workspace. When Go builds your application, Go will use the dependencies in whatever workspace your $GOPATH is set to. When $GOPATH is set to ~/golang/packages1, Go stores our package there. When we change $GOPATH, and grab a new package, our new package is stored in the new $GOPATH directory. So in our example, each directory only has 1 package, even though we’ve installed two packages (web.go and Go-Redis). Each package was installed in a separate location, and can only be accessed when $GOPATH points to the correct location.

Why does an environment variable control you package dependency location? Well, it allows you to:

  • Have different versions of libraries built with different applications that you create.
  • Make custom modifications to packages that only affect one application that you build.
  • Distribute build environments to other developers on your team, without mucking up their current environment.

Notice that we haven’t mentioned $GOROOT for a little while. $GOROOT deals with the Go binaries and standard library, the Go language itself. $GOPATH has to do with packages that you work with when building applications.

You can do a lot of different things at this point.

  • Modify your ~/.bashrc file and export GOPATH, just as you did with GOROOT.
  • Export GOPATH manually each time you work with a different application.
  • Source a file that will set your build environment (and $GOPATH) in your app’s root directory

Let’s do one final experiment and install the Go tour.

$ export PATH=$GOPATH/bin:$PATH
$ go get code.google.com/p/go-tour/gotour
$ ls packages2/bin/ gotour
$ gotour
2012/09/29 10:28:46 Serving content from /home/rday/go/packages2/src/code.google.com/p/go-tour
2012/09/29 10:28:46 Open your web browser and visit http://127.0.0.1:3999/

Success! You have a working Go installation!