Understanding Go Dependency Management

Right now there is a discussion thread on the golang-dev mailing list about formalizing how Go manages dependencies. The Go Team is putting forward that Go use vendoring to manage dependencies, and asked the community to formalize a configuration format that tools can use to manage vendored code.

For sometime the Go team has been very passive in directing how Go manages dependencies. When Go was first released to the public the only mechanism or best practice was to use go get which is not much more than a simple tool to fetch code.

The passiveness on the part of the Go team was deliberate. They themselves didn’t see the best solution to dependencies and wanted to let the community discover for itself what worked and didn’t work when using Go in the real world. There was even a mailing list setup by the community to discuss the different ways this could be achieved.

The current thread on the mailing list is looking to formalize practices that teams inside Google, and in the community have adopted, and to standardize a configuration format to unify best practices. This helps different tools understand and work with dependencies in the same way.

What is vendoring?

Vendoring is the process of moving library code that your program depends on into your own project’s source. Then you need to manipulate your $GOPATH to include the vendored directories, or rewrite your source code’s import paths to point to the vendored version instead of the original. Rewriting import paths is the solution suggested by the Go Team. Such as /myProject/third_party/github.com/someDev/externalLibrary.go

The recommendation suggests vendored code will live under the internal directory in a project. Internal is a named directory who’s code can only be imported into the current project, regardless of symbol visibility.

The benefits of vendoring are that you have the version of the library that know works with your program. You are not relying on external services or people. The code won’t update unless you update it. When you share you code with other developers they get the vendored libraries along for the ride.

Some have voiced concern against vendoring. That it is easy to do in one large company, such as Google, but difficult when faced with the chaotic nature of collaboration in the real world.

A common config file

More discussion has surrounded the specifics of what kind of configuration file to use, and how to organize the information within it. The hope is use a format that the existing standard library can read and use, and since no one wants to use XML, it’s between JSON or a .go file.

godep already uses a JSON file, and would be a good starting point. But JSON doesn’t support comments, a very useful feature to be had.

A few people have put forward using a vendor.go file as the configuration, using a struct to store information about dependencies. Others have wondered if this was overkill, or pointless. Which was replied that having the full power of go for dependencies offered abilities that a static configuration file alone could not. That the vendor.go file could be treated like *_test.go and ignored on build, but could offer powerful options in the future has has been seen with Clojure’s build tool Leiningen. Which could help with tool automation.

Dependency goals

The overall goal at this point is to standardize existing practices that the community uses, and agree on a configuration format that existing tools can adopt. No changes to any go commands were promised for 1.5 at this time, but should be reevaluated for 1.6+.

For the time being existing tools will should migrate to whichever solution is accepted by reaching a consensus.