July 19, 2014 shurcooL Go
First off, I want to make it clear I have a fixed GOPATH that I do not change per project. The GOPATH env var is set inside my ~/.bash_profile file and doesn’t change. Every Go package I have exists in no more than one place. I tend to have all my personal dependencies on latest version, simply because it’s easier to have everything up to date than any alternative.
I do make use of the fact that the GOPATH environment variable is defined as a list of places rather than a single folder.
The GOPATH environment variable lists places to look for Go code. On Unix, the value is a colon-separated string. On Windows, the value is a semicolon-separated string. On Plan 9, the value is a list.
My GOPATH consists of 3 folders or GOPATH workspaces.
The first one is my landing workspace. Since it’s listed first, whenever I go get any new package, it always ends up in this workspace.
Go searches each directory listed in GOPATH to find source code, but new packages are always downloaded into the first directory in the list.
I make it a rule to never do any development in there, so it’s always completely safe to clean this folder whenever it gets too large (with Go packages I don’t use). After all, it only has Go packages that I can get again with go get.
My second workspace is for all my personal Go packages and any other packages I may want to “favorite” or do some development on. I move things I use regularly from first workspace into second.
My third workspace is dedicated to the private Go packages from my work, and their dependencies. It’s convenient to have my work packages separate from all my personal stuff, so they don’t get in each other’s way.
With that setup, multiple GOPATH workspaces feel a lot like namespaces. The reason I have more than one, to me, is quite similar why one might want to break a medium-sized Go package into several .go files. The result is effectively the same since multiple .go files share the same scope but allow one to have “namespaces”.
Similarly, multiple GOPATH workspaces share the same scope (i.e., it’s your “effective GOPATH”) but allow you to have namespaces for categories of packages. Having 3 GOPATH workspaces with 100 packages each is no different than 1 GOPATH workspace with 300 packages. They don’t overlap, similarly to how code in multiple .go files of a Go package doesn’t overlap.
As long as multiple GOPATH workspaces are a supported feature, I don’t see the motivation to actively force yourself to use only one GOPATH workspace. You should do whatever is optimal for your particular use case.
That said, I feel that having 2 GOPATH workspaces is nice just because it lets you easily “undo” go getting a package you no longer want to keep by having the first GOPATH workspace act as a temporary place. If I had to have just one GOPATH, I would feel very hesitant before doing go get on any new, unfamiliar Go package. What if it brings in 100 dependencies and I decide I don’t want to keep it anymore? Undoing a go getcurrently is not straightforward… Unless you use 2 GOPATH workspaces and don’t mind simply blasting the first one away.