When Go was first released a gap between what developers needed and what the
go tool provided became apparent. That was the management of vendor packages. This quickly lead to the rise of applications such as Godep and GPM to fill in the gap. With the release of Go 1.5 comes changes to the
go toolchain that starts to natively address the gap. In this post I'll talk about how it works and how you can leverage it.
Packages in Go need to live within the
go toolchain makes certain assumptions and problems arise when packages are outside the
GOPATH or when you have multiple directories in the
Traditionally, you can only have one version of a package in your
GOPATH and using
go get retrieves the latest version on the master branch. It isn't setup to retrieve a specific version. What happens when two developers get different versions of a dependent package to the one they are working on? Or, what happens when you're working on two packages that require different versions of the same dependency? You can easily end up with unreproducible environments.
To fix this tools such as Godep and GPM stepped in with hacks around the problem. For example, Godeps allows you to take a snapshot of your dependent packages to store in a subdirectory and then others could restore that version.
If only the Go toolchain helped solve this problem.
The Vendor Directory
With the release of Go 1.5 there is a new opt-in feature (that's planned to be on by default in the future). It provides a way to specify vendor packages in a way the Go tool can work with.
First, you need to set the environment variable
1. This is how you opt-in at the moment. Once you do that your project can have a special vendor directory containing your dependencies. The layout looks like:
- GOPATH/src/github.com/example/foo | - main.go - vendor/ | - github.com/ | - foo/bar - Masterminds/vcs
Your project lives in the
GOPATH normally. But, your projects dependencies can live in the
vendor/ directory. When
go looks up a package referenced in the source it will look in the
vendor/ directory, then look in the
GOPATH, then look in the
GOROOT (where standard library packages such as
This allows you to have versions of dependent packages specific to a package in on place with no hacks.
This even works recursively. For example, if one of your dependent packages has a vendor directory with dependencies in it those will resolve as well. And, if two dependent packages have different versions of the same dependency the right one will be used.
This recursive nature can introduce sideways problems so I recommend paying careful attention when using it.
go tool in 1.5 does little more than what I just described. So, how can you manage the packages in the
This is where I'll get a little opinionated. When the release of Go 1.5 we pivoted Glide to be a support tool. The goal is to help others be successful with this new way to work with dependencies.
Glide provides a way to document, fetch, and manage the dependencies within the
vendor/ directory while working cleanly with the
go toolchain. It tries to compliment the functionality in Go.
You can use Glide to repeatedly install the same dependency versions between different environments and developers. You can think of this as something similar to npm, composer, bundler, and the package managers used by other languages.
If you want to vendor the dependencies from vendors, that is store the source files for the dependent packages in your source control system, Glide will work as well.
Glide has lots of other management features and we plan to continue development down this road to try and make things easy.
Note: there are other tools for managing dependencies in the
vendor/ directory. When choosing one be sure you understand the purpose of the tool and where it's going.
The Bright Future
Other languages and platforms have come to some great patterns and the Go toolchain with the surrounding ecosystem is heading in a good direction. I look forward to the bright future ahead of us.