Overview

I recently migrated some of my project’s dependency management tools from dep to go module, and there are some cool things and some not so cool things about it, so here’s a brief overview of some of my personal opinions and feelings about the migration process.

First of all, as of the time of writing this article, the latest release of Go is 1.16.

dep

Benefits

  • Specifying versions is friendly

    Dep supports specifying a specific version of a package in Gopkg.toml, and supports various semantics, such as

    • version: specifies the use of a specific version, either >, =, < ... ...
    • branch: specifies that a specific branch is used
    • revision: specifies the use of a specific commit
  • Support for saving packages that are not used in the code

    Dep can filter dependencies that are not used in the code with the ignored option, which is useful for referencing some tools. For example, if we create a mock tool, we can put it directly in the vendor and install it with go install vendor/xxx when we ci; in the go module, we can’t. A common usage is to create a tools.go file and then import _ xxxx

pain points

  • Unstable connection management

    This is the point that most students complain about, that is, dep often a dep ensure command is a day, and then still can not finish, this is actually dep connection management and retry problems; in addition, there is also the problem that dep’s local cache is not handled very well, often there is a remote master branch has been updated, but the local cache Because it is in another branch (for example, the release branch of v5), but dep just can’t react and won’t switch to the master branch or something, and then it reports an error when you dep ensure that you found the version you want.

    In this case, my usual way to deal with it is to rm -rf $GOPATH/pkg/dep/sources/git---xxxx clear the local cache and then dep ensure once more.

  • Unable to update a specific package

    For example, if I want to update only one version of github.com/pkg/errors and no other unrelated dependencies, then sorry, this is not supported and I have to use dep ensure to update all packages.

    If I’m so stubborn that I just want to update this package, fine, I need to specify the current version of all other packages directly used by the project in Gokpkg.toml, so that they won’t be updated.

  • Strange package management

    • For example, if I want to add a dependency, if I already have import github.com/pkg/errors in my project, then I use dep ensure -add github.com/pkg/errors to indicate that I already use this package, and if I want to update If I want to update this dependency to Gopkg.lock, then I have to dep ensure

go module

Benefits

  • Multi-version support

    If your project wants to use multiple versions of a module at the same time, e.g. the main code uses the latest version of a module, but you need to use an older version of the module for some API calls due to compatibility with older interfaces and so on, then go module can help you do that, because it supports specifying the version when importing the module.

  • Support for environment variable settings

    Commonly used ones are

    • GOPRIVATE: private project, does not use Proxy
    • GOPROXY: proxy support, especially useful for intranet CI
  • Simple and straightforward package dependency management

    For example, if I want to add a new dependency package, I can directly use go get xxx to add it to go.mod; if I want to upgrade, I can directly use go get -u; if I want to specify the version, I can also directly use go get xxx@commit-id.

  • Support for undoing releases

    This is a new feature, if you use a wrong release, then go mod will alert you and you will need to upgrade or downgrade.

Disadvantages

  • Package versioning is not friendly

    Although the package dependency management of the go module is simple, it is not friendly for some tags. For example, if I want to install a v5 tag: go get github.com/godbus/dbus@v5.0.3, sorry, you will have this problem: ``

      [root@liqiang.io]# go get github.com/godbus/dbus@v5.0.3
      go get: github.com/godbus/dbus@v5.0.3: invalid version: module contains a go.mod file, so major version must be compatible: should be be v0 or v1, not v5
    

    So, what do I need to do? The following two ways are officially allowed, of which the first one is recommended (although I feel awkward, people do consider it a feature, see Advantage 1).

      [root@liqiang.io]# go get github.com/godbus/dbus/v5
    
      [root@liqiang.io]# go get github.com/godbus/dbus@37bf87eef99d69c4f1d3528bd66e3a87dc201472
    

Contrast feelings

  • Everyone supports replacing the source address of the package
    • dep: override
    • gomodule: replace
  • Everyone has the ability to create and populate vendor directories
    • dep ensure --vendor-only
    • go mod vendor
  • None of them work well for private projects
    • Untrusted github on the intranet
    • Private projects on github
    • Both scenarios need to be solved by setting up a local git config

The only feature that makes me miss dep is the precise version specification. In go module, you can’t specify it precisely, and even if you do, it’s still considered the minimum required version “>=”, and it’s likely that the version of this package will be changed later because of other dependent Of course, occasionally it is possible to meet your specification and use the version you want.

Ref