How I use GOPATH with multiple workspaces

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 get currently is not straightforward... Unless you use 2 GOPATH workspaces and don't mind simply blasting the first one away.


skovtunenko commented 8 years ago

Thank you! This info really helpful.

Write Preview Markdown
edoardoc commented 6 years ago

Very nice explanation!

Write Preview Markdown
wemgl commented 6 years ago

Great article! Thanks for sharing it. It was very helpful.

Write Preview Markdown
hemenkapadia commented 5 years ago

Conceptually i like this as it aligns with the way I like to organize the projects on my machine. However when trying to use dep ( with such a go path always results in the error

init failed: unable to detect the containing GOPATH: is not within a known GOPATH/src

The workaround i found to get dep working was to modify GOPATH for that single command

GOPATH=/home/hemen/Workspace/Personal/go dep init

Not sure how this workaround will come to bite me later. Any thoughts on this ? Or a better suggestion ?

Write Preview Markdown
dmitshur commented 5 years ago

@hemenkapadia It might be worth asking that question on a dep forum. I am not familiar with it, so I can't say. I would expect that it should not fail on a GOPATH variable containing multiple entries.

Write Preview Markdown
to comment.