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 thego.modfile. If yourmoduleline specifiesfoo.com/bar/baz, you need to put your project in$GOPATH/src/foo.com/bar/baz. It’s themoduleline that matters, not the URL to the actual project. - Use
GOMODULE111=onwhen you’re dealing with dependencies. By default, when you’re inside ofGOPATH, modules will be disabled. You need to manually enable them in order to add and update dependencies withgo mod ...subcommands, orgo 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 withGOMODULE111=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!