> Instead, just look at go.mod. It lists the precise version at which all dependencies are built.
No, it does not. Minimum version selection means that the libraries will at least be that version, but it could be substituted for a later version if a transient dependency asks for such.
That I'm reading this blog post at all suggests there is a "market" for a single checksum/version manifest, which data is currently housed in go.sum . This is sad, but, Hyrum's Law and all that.
A lock file, in my world, contains a cryptographic hash of dependencies. go.mod does not, it only lists tags, which are (in git) movable references.
If go.sum has "no observable effect on builds", you don't know what you're building and go can download and run unverified code.
I'm not a go developer and must be misunderstanding something...
The pyproject.toml, package.json, and Cargo.toml are declarative project configuration files. While the Rust community refers to Cargo.toml as a manifest, it is not a comprehensive and detailed list of a build. That is the lock file.
While go.mod does not allow for explicit version ranges, the versions given are the minimum versions. In other words, the versions given are the lower bound of the compatibility range.
Go also strictly follows semantic versioning. Thus the implicit exclusive upper bound is the next major version. This assumes that all minor and patch releases are backwards compatibile and not breaking.
Dependency resolution in Go uses minimum version selection. That means the minimum requirements of all dependencies are evaluated and highest minimums are selected. In principle, this minimum version selection should be time invariant since the oldest versions of the compatible dependencies are used
While the minimum versions specified in go.mod are not necessarily the version of the dependencies used, they can be resolved to the versions used irrespective of time or later versions of dependencies being released.
Other languages do not use minimum version selection. Their package resolution often tries to retrieve the latest compatible dependency. Thus a lock file is needed.
Python packages in particular do not follow semantic versioning. Thus ranges are critical in a pyproject.toml.
In summary, the "manifests" files that the original author describes are configuration files. In some languages, or more accurately their package management schemes, they can also be lock files, true manifests, due to version semantics. If those semantics are absent, then lock files are necessary for compatibility.
nice, if a module like github.com/foo/bar v1.2.3 is later modified or compromised upstream, the checksum in go.sum will cause the build to fail unless the exact same content is fetched.
Correct, but it's been ages and the default actions/setup-go github action still uses go.sum instead. I see that someone already commented on the longstanding issue to reference this post, and that there is some hope that they'll update it!
Two very similar things are presented as though they are different (go.mod and lockfiles, not go.sum) for the purpose of sneering at one of them, when both are essentially the same. 'Ignored by downstream dependents' is not any less true of go.mod than of lockfiles. In both cases a later version can be demanded, overriding the earlier version, potentially breaking your code.
npm's package.json and package-lock.json get out of sync constantly on my team. at least go only has one file to mess up
I am today years old to find this...
>If the main module imports example.com/mod1/pkg1 and a separate example.com/mod1/pkg2 imports example.com/mod2, there is no way for example.com/mod2 to affect the build or run code on the developer’s machine, so you don’t need to consider it a dependency.
iirc (I do not have a test setup at the moment to verify) it does affect your dependency resolution, and therefore your build, though its code does not exist in your binary. I know this because those AWS / K8S / Google Cloud libraries cause MASSIVE problems with their constant breaking changes without major version changes, and their importing other libraries that also have frequent breaking changes without major version changes, even if the dependency those unused subpackages include (and therefore raise the minimum version) is only used by some other module that needs a lower version (iirc). It's quite a headache sometimes, and could be rather easily solved if you could set upper bounds and not just lower. Or if those giga-projects would stop doing such obviously bad things.
The version-affecting behavior is kinda unavoidable afaict. If they didn't include those unused version constraints, `go build ...` or just importing a new package within existing modules could cause your build to fail, forcing you to rerun version resolution. That'd probably just lead people to feel like "go is broken UGH", and go leans awfully hard towards avoiding that kind of thing. Mostly for the better, but not quite always / not in all ways.