DAVID ZHANG
<< Back
Go Module in Action

For a long time, Golang provides an extremely simple dependency management model. It just depends on Git repos and actually its master branch.

If you have experience on concepts and tools like monorepo/Gerrit, you can easily get the point why it was initially designed like this1 including the existence of GOPATH. That is because Google uses monorepo.

There are some advantages claimed2 and Golang’s dependency management could work on that well.

However, monorepo does not dominate the world. The dominance of open source community is GitHub. In contrast, GitHub follows fork & pull request workflow.

This (Go’s dependency management design) leads to lots of issues:

  • No tag, no semver. When master makes breaking change, it breaks build.
  • Not compatible with GitHub’s fork model, unless you make some hack on Git remote3.

To make it easier, there are some efforts:

By these tools, we may handle vendors better. But these tools are not officialy supported and it needs commit all vendor packages to repository! Can you imagine a frontend or Node.js project commits its node_modules? This is ridiculous.

Go Module

I don’t know the decision process, but Golang team finally launched Go Module in 1.11, which embraces the non-monorepo part of the world.

  • No GOPATH, and now we can clone to anywhere.
  • go get inside a repo is not global, it works only at local.
  • No vendor
  • Dependencies are defined in go.mod with git tags, commit hashes, and semver.

HOW TO

  1. Install or upgrade to Go >=1.11 (currently 1.12)
  2. Enable Go Module, edit .bashrc or .zshrc:

     export GO111MODULE=on
    
  3. Initialize Go Module

     go mod init .
    

Commands

  • Add missing and remove unused modules
go mod tidy
  • Add new module
go get github.com/crispgm/go-g
  • Update a module
go get -u github.com/crispgm/go-g
  • Update all modules
go get -u
  • Get specific version of module
go get github.com/crispgm/go-g@master
go get github.com/crispgm/go-g@1.0.0
go get github.com/crispgm/go-g@617f32e
  • Make vendored copy of dependencies
go mod vendor

I highly not recommend this, since getting rid of vendor is one of the major advantages of Go Module.

Editor’s Support

VSCode

There is a Go modules support guide in vscode-go plugin. It is actually very easy that we just need to enable Language Server for go by adding one line to settings.json:

"go.useLanguageServer": true

Troubles Encountered

  • “Dependency’s Dependency”

One of our in-house library depends on satori/go.uuid, with traditional go get it means depend on master. But Go Module got the latest tag by default. So the solution should be:

go get -u github.com/satori/go.uuid@master
  • Got “ambiguous import: found github.com/ugorji/go/codec in multiple modules”

It is actually caused by gin-gonic/gin (the web framework we use) and there is a solution:

Add the following to go.mod to solve the trouble.

replace github.com/ugorji/go v1.1.4 => github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43

Conclusion

Go Module is not a silver bullet, and it is more a compatibility than a fix. But for me, it is great improvement.