Cleaning up my GOPATH with Homebrew

tl;dr: use the script at the bottom to go get into the Homebrew "Cellar" and keep your GOPATH clean.

I personally like GOPATH and import paths, but while trying to reduce my laptop to a thin reproducible client, I felt the pain of keeping track of the hundreds of repositories that end up in there.

The problem is that there are too many reasons for things to be in there:

  1. code you're actively working on
  2. dependencies of that code
  3. tools you installed and their dependencies
  4. tools your editor installed and their dependencies

1 belongs there. So much so that after cleaning it up I set my GOPATH to $HOME and got rid of my ~/code folder. All my code--whatever the language--is now in ~/src, with unpublished code in ~/src/filippo.io.

2 doesn't, and should just go directly into the vendor folder. That's why I made gvt back then, and I'm happy to see that dep will do the same, if I understand correctly.

4 can be fixed, for example for Visual Studio Code:

"go.toolsGopath": "~/.vscode/gopath"

That leaves only 3. The repositories that show up because you want to install some nice Go tool.

The fact is, go get was never meant to be a software distribution tool. Homebrew is. Homebrew also comes with hashes for everything, so when a tool is available from Homebrew I now prefer installing it from there. But sometimes it isn't.

One of my favorite features of Homebrew is that it's easy to install something manually into its "Cellar", and then let brew take care of linking it into /usr/local, making tracking, switching versions and uninstalling a breeze.

So I made a simple script that will go get a binary (or multiple) into the Homebrew "Cellar" and link it, fully insulated from your system GOPATH. Here's how you use it:

$ brew-go-get golang.org/x/perf/cmd/benchstat
Linking /usr/local/Cellar/go-get-benchstat/2017-08-12... 1 symlinks created

$ brew-go-get golang.org/x/perf/cmd/benchstat
Unlinking /usr/local/Cellar/go-get-benchstat/2017-08-12... 1 symlinks removed  
Linking /usr/local/Cellar/go-get-benchstat/2017-08-13... 1 symlinks created

$ brew uninstall go-get-benchstat
Uninstalling /usr/local/Cellar/go-get-benchstat/2017-08-13... (8.5MB)  
#!/bin/bash
set -euo pipefail

if [[ $# -lt 1 ]]; then  
    echo "Usage: brew-go-get github.com/foo/bar ..."
    exit 1
fi

NAME=$(basename "$1")  
VERSION=$(date '+%Y-%m-%d')

unset GOBIN  
export GOPATH="$(brew --prefix)/Cellar/go-get-$NAME/$VERSION"

go get "$@"

rm -rf "$GOPATH/pkg" "$GOPATH/src"

brew unlink "go-get-$NAME" 2> /dev/null || true  
brew link "go-get-$NAME"  

For more Go and obsessive laptop cleanups, you can follow me on Twitter.

(I know I could have made a Homebrew command instead, but Ruby. If you feel like making one, it would be super cool if it could also handle upgrades automatically!)