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
- version: specifies the use of a specific version, either
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 thenimport _ 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 thendep 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 usedep 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 usedep 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 todep ensure
- For example, if I want to add a dependency, if I already have
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 usego get -u
; if I want to specify the version, I can also directly usego 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.