We recently started using go modules at work to handle dependencies. The experience has been mostly great, but unfortunately a lot of tooling hasn’t added support for modules. Most of the team uses vscode, which depends on module support in open-source tooling, some of which is incomplete. At the time of writing, refactoring/rename tools don’t work, and many of the other tools are very slow when modules are enabled. I wanted to find a way to use modules for dependency management, but use GOPATH for development. It turns out that it’s fairly easy to get the best of both worlds if you follow a few simple rules:

Put your project in GOPATH in the correct location defined by the go.mod file. If your module line specifies foo.com/bar/baz , you need to put your project in $GOPATH/src/foo.com/bar/baz . It’s the module line that matters, not the URL to the actual project. Use GOMODULE111=on when you’re dealing with dependencies. By default, when you’re inside of GOPATH , modules will be disabled. You need to manually enable them in order to add and update dependencies with go mod ... subcommands, or go get . These dependencies are what our builds use, and will be deterministic. One catch: when you alter dependencies with modules, you must run go mod vendor , still with GOMODULE111=on . This will save your dependencies to ./vendor , which will allow non-module-aware tooling to function.

A good test to see if things are working correctly: you should be able to open a module-enabled project in vscode and use gorename to change a symbol name.

PS - We’re hiring go folks!