Multiple GOPATHs

Sometimes you want to work on different changes in parallel - most importantly, to be able to run a slow test on one change while developing another change. For this we need multiple clones of our repository (or multiple worktrees, see git-worktree.

Because of the way package paths work in go having multiple copies of the same repository in the same GOPATH is difficult to achieve. The solution simply to set up multiple GOPATHs. Each directory will have a full copy of all project dependencies. We could set up /go and /go2:

export GOPATH=/go
export PATH=$PATH:$GOPATH/bin
sudo mkdir -p $GOPATH
sudo chmod a+rwx $GOPATH
mkdir -p $GOPATH/bin $GOPATH/pkg $GOPATH/src/github.com/cockroachdb
cd $GOPATH/src/github.com/cockroachdb
git clone git@github.com:UserName/cockroach.git  # Replace with your username
cd cockroach
make
# Repeat the above with GOPATH=/go2

We can set up some symlinks to easily go to each repository:

ln -s /go/src/github.com/cocroachdb/cockroach ~/roach
ln -s /go2/src/github.com/cocroachdb/cockroach ~/roach2

The problem is managing GOPATH and PATH. This simple script can help, I have it as ~/bin/gopath.sh:

if [ -n "$1" ]; then
    BASE="$1"
else
    # Try to deduce the GOPATH as the root-most dir in the current path
    BASE="/$(pwd -P | cut -d "/" -f2)"
fi


if [ ! -d $BASE/bin -o ! -d $BASE/src -o ! -d $BASE/pkg ]; then
    echo "$BASE doesn't look like a go path!"
    exit 1
fi

# remove $GOPATH/BIN if it's there
if [ -n "$GOPATH" ]; then
    PATH=$(echo "$PATH" | sed "s#:$GOPATH/bin##g")
fi

echo "Setting GOPATH to $BASE"
export GOPATH=$BASE
export PATH=$PATH:$GOPATH/bin
echo "Path updated to $PATH"

Note: this script assumes the GOPATH is a directrory under /

We just need to call gopath when we first cd into our repository. I have each terminal/tab "dedicated" to one repository, so I don't need to switch back and forth in one session.

~ $ cat ~/.bashrc | grep gopath
alias gopath=". ~/bin/gopath.sh"

~ $ cd ~/roach

~/roach $ gopath
Setting GOPATH to /go
Path updated to /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin:/root/bin:/go/bin

~/roach $ cd ~/roach2

~/roach2 $ gopath
Setting GOPATH to /go2
Path updated to /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin:/root/bin:/go2/bin