The Go module not only follows the semantic version specification 2.0.0, but also goes a step further by giving deeper meaning to the
major in the semantic version.
X.X: For the case where the major version number (
0, it implies that your current
APIis still in an unstable state, and the new minor version may not be backward compatible.
X.X: the current
APIis in a stable state, the increase of
minoronly means the increase of new
APIis still backward compatible
- X.X: the addition of
majormeans that the
APIis no longer backward compatible
Question: Do you know which version numbers in the go module imply that the current API is unstable?
But what sets
go module apart from the rest is that once your
major is greater than or equal to
module path must be suffixed with
v3.X.X, then it is suffixed with
v3, and so on).
v2 to the package reference path, e.g.
This is an odd way to write it, equivalent to putting a salve on the normal easy-to-understand
module path to indicate which version of the library is being introduced?
Why add this
v2 suffix, there must be some considerations
Most notably, the developer of Go (in this case Russ Cox) pointed out in the import compatibility rule:
If an old package and a new package have the same import path, the new package must be backwards compatible with the old package.
This idea is a good one. For example, you can use multiple versions of the same library in your project, with
v1 versions handling previous legacy logic,
v2 versions handling new logic, and
v3 versions experimenting with future versions. Different versions of the same set of libraries can coexist and there is no place for version conflicts.
And when programmers see these
module paths, it is clear that the versions are not compatible and who is the newer version.
But this way is also very controversial, in practice also brings a lot of problems, I am in the development of
rpcx suffer from it, and
etcd, for example, you can see its
v3.4.X version, is because there is no
v3 suffix, resulting in
go command to download or import (
package when it simply can not be downloaded.
The vX suffix contaminates the package path
Originally, the normal
package path is generally the repository path +
package name, or
go module under
module path +
package, but once the version is greater than or equal to
2, you have to add a suffix
v3, etc., the meaning of
package path has changed.
Of course, we can tolerate it, the big deal is to close our eyes and use it, but the most painful thing is that many
Go beginners do not understand this setting, do not know to import the new library version to add the v2 suffix, a face of confusion.
v0, v1 and v2 data types are not compatible
v3 and other suffixes to
module path, it is assumed that these
package are different
package, although most of their data types are not changed, or backward compatible, and cannot be assigned directly, but still need to be strongly transferred.
For example, if your project depends on
Auth 1.0.0 and also depends on
Auth 2.0.0, then even if
A.Config doesn’t change in both versions, you can’t assign
Auth/v2.Config, but you need to add the logic of strong transfer in the code, so that the two are transferred to each other. Once
v3 is released, it’s a long
switch branch to deal with this situation, and if
v4 is released, the logic is even more complicated.
Impose a significant burden on third-party library developers
Although you think I also release
v4 and several other versions, the version route is very clear and not complicated to manage, no big deal.
However, if your library is a very popular library and many developers have developed third-party libraries based on your library, it can be very painful
This means that once you release a new version, these third-party developers have to update their libraries in time to release their new
v3 versions based on your new version. This is like a virus that initially expands. It’s a big burden to the developers.
Of course, it is a matter of opinion, these situations may not be encountered by you, or will not bring you trouble, so it is not a problem. I, on the other hand, was deeply hurt by
v2 when I was developing
rpcx or answering some users’ questions, and my little mind couldn’t bear the weight of
Some open source projects, in order to avoid the version number jump to
v2, using some other methods, such as
protobuf-go, is doing a new version of the refactoring, the changes are very large, not compatible with the previous version, can be the previous version are
v1.X.X, then how to do? Change the
module path name.
github.com/golang/protobuf: support for the previous
protobuf go, currently up to version
google.golang.org/protobuf: new version of
module path, current highest version
v1.27.0, initial version
rpcx project, because the version number was released to
v6.X.X before the
go module came out. I want to go back to the old days, but it seems that I can’t go back. So I took an extreme approach and rebuilt
tag with all the version numbers defined in
v1.X.X. Fortunately, it affected fewer users, so no users complained.
My approach is rather extreme, but the reason I didn’t cause users to complain is that I always insist on the coexistence of
go module and
GOPATH. The vast majority of users use the
master branch, or
fork a new version themselves, so the impact is minimal.