The Golang (Go) community is a passionate one. That passion results in excellent discussions and lots of great ideas, especially when it comes to improving the language and its ecosystem. But that passion can also divide the community when not everyone agrees on the best way forward. For example, when it comes to versioning and dependency management, the community-led ‘dep’ experiment looked poised to establish itself as the defacto standard until the introduction of vgo and Go modules earlier this year.
Vgo + Modules
Vgo is the reference implementation of Go that attempted to deal with versioning in general, and dependency management in particular. Vgo has resulted in the introduction of modules to deal specifically with dependencies and their versioning. As of this writing, the Go modules proposal has been accepted. Go v1.11, released August 24, 2018 added provisionary support for modules, with final support being slated for Go v1.12 due January 1, 2019.
However, the community has been resistant to adopting modules.
For those that aren’t aware, Go modules provide a way to denote a collection of Go packages that are versioned together as a single unit. The implementation requires you to create a Go.mod file in your root directory to tell Go that this is a Go module, as well as to use versioned import paths. While the Go.mod entry allows you to use > to specify a set of versions that are valid, your actual code needs to call the specific version number. Now, if a library you use is upgraded from version 2 to version 3, you’ll need to revise your code. While this approach certainly helps guard against applications breaking, it results in all kinds of extra manual work for the developer. And of course, legacy code will need to be migrated to the new module format.
We recently hosted a vigorous live-streamed roundtable on dependency management, reproducible builds and environment config with Russ Cox (the creator of vgo), Sam Boyer (who led the dep project), and Jess Frazelle who was on the working committee. You can watch the on-demand video here.
Versioning & Dependency Management
Speaking of legacy pains, just the fact that your code doesn't need to live in GOPATH anymore is a big benefit. GOPATH was an extremely rigid way of working that differed from the project-based method every other programming language uses. Developers expect to work with code in their project folder, but for Go, your code had to live separate from everything else. This non-intuitive way of working has been a drawback to Go adoption, holding back the growth of the language.
When it comes to dependency management, the existing dep solution is well liked due to it’s relatively non-restrictive usage: just import a library and dep will grab whatever version of that library it can find. Go modules take a different approach, requiring a Go.mod configuration file and the use of semantic versioning to state which resource you’re importing.
Things get even more complicated with management of interdependencies. As an example, let’s say resource A requires resource B, which requires at least v1.0 of resource D. But resource A also requires resource C, which requires v1.0 or v1.1 of resource D. Vgo has a fairly controversial version selection algorithm built into it that will always choose the oldest version that works for all cases - in this case, v1.0 of D. Most other languages choose the latest viable version, as does the existing dep solution. Defaulting to the oldest viable version is great for stability, since newer versions may not be as well tested/proven, but it may also perpetuate vulnerabilities which have been fixed in newer versions.
The versioning and dependency management problem in Go is not settled by a long shot. The Go Team and community still have a lot of work to do to address the shortcomings that have been raised. As always, these problems require lots of communication, time, and hard work to solve. Versioning and dependencies are a huge barrier to enterprise Go adoption. It’s in everyone’s interest to resolve these problems and have a clear path forward sooner rather than later.
Interested in trying Go for yourself? Get started quickly and easily by downloading ActiveGo.