- version constraints - source of packages (you may want to host them yourself one day) - any additional metadata (some packages have options or features)
- version constraints - source of packages (you may want to host them yourself one day) - any additional metadata (some packages have options or features)
For example… let’s say you have just plain search-replace and no smart tools. You need to update github.com/abc/def to github.com/abc/def/v2. This is a search-replace operation.
This only happens when packages publish breaking changes. The minor version is stored in go.mod.
gofmt -w -r '"github.com/abc/def" -> "github.com/abc/def/v2"' .
That won't do subpackages though.
Every language starts the way you describe, then needs are added.
What is complex versioning? In Go, you specify a minimum minor version, and breaking changes change the package name & import path (or they’re supposed to). Why would I want complex versioning? The underlying problem that versioning solves is complicated, but that doesn’t mean you benefit from a complex versioning scheme.
Nowadays, the version constraints are specified in go.mod. Because the fully-qualified package names are used to import them, you can reconstruct go.mod from the sources, assuming that you don’t care about version numbers.
The source code says which packages, the go.mod file says which versions. (Major versions have different import paths.)