Go Modules: The Best of Both Worlds
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
GOPATHin the correct location defined by the
go.modfile. If your
foo.com/bar/baz, you need to put your project in
$GOPATH/src/foo.com/bar/baz. It’s the
moduleline that matters, not the URL to the actual project.
GOMODULE111=onwhen 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!