-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Description
Hey together,
I just came across your go.mod file. I have to admit I am a bit confused how you decided the values of the go and toolchain directive and I think those should be changed... π€
Let me explain this.
Note
I am not an go developer by day. Also the toolchain feature is fairly new in the go ecosystem.
Therefore it might be the case that Iam totally wrong with all of this here. If so, please let me know π.
Starting with go 1.21 the behavior of the go directive in the go.mod file changed. Before that version, the statments acts more like an "information". It just indicates what go version that module needs to be compiled with. However, go was not very strict with that. If you used an go version lower than that, go just tried to compile the module. If its succeeded, it's fine, otherwise it's throws an (compile) error.
In go 1.21 the go statement indicates the minimum go version required to build that module. Same as before, but now more strict.
See the docs here
https://go.dev/ref/mod#go-mod-file-go
In go 1.21 they also introduce the toolchain directive. With that you can create reproducible builds across the developer (and CI) toolchain. As go will make sure it will always use that exactt go version to compile the module. It does this by downloading the specified go version if your local go version is lower than that.
See the docs here
https://go.dev/doc/toolchain
With that change, they also changed their versioning. In the past a major.minor version was released. They changed that to release a full semver version instead. With that said, to a major.minor.patch version. (Notice the .patch π)
See the docs here
https://go.dev/doc/toolchain#version
I guess using a non-patch version for higher go versions than 1.21 will only work because of backwards compatibility.
But in fact, it is "wrong". Or at least not considered as best practise anymore.
How does this relates to this project?
In this PR @matthewhughes934 wanted to fix your go.mod file by introducing the patch version. He also provided a lot of useful links there.
(Note: I don't know why he faced the docker issue, I am not an expert in that field. But regardless of that error, using a patch version is more correct!)
You can checkout his first commit in this PR to see his change:
9fae21f
For reasons he decided together with @williammartin to introduce the toolchain directive.
That also fixed that issue. But not because "it is more correct" (to fix that specific error). But instead it would solve that problem because with the toolchain feature, go will look at this (and download the correct version) and not at the (still wrong) go directive.
I guess π«
Later this PR were opened.
Besides of other changes, the go directive was changed to 1.22.0 (so basically what the first PR also wanted to do π ), AND the toolchain was changed to 1.22.5 (from 1.22.2).
Here is also a nice comment by @williammartin on that PR, saying "we should report upstream that using a patch version is "wrong"". However, as already pointed out above, using a patch version is actually there more correct usage now. There is no release in go without a patch version anymore!
So actually using 1.22.0 is correct, while using 1.22 for the go directive is just wrong.
Something about CI.
Right now you are using the setup-go action together with the go-version-file: 'go.mod'.
Because you also declared the toolchain directive, you download right now 2 versions on your CI.
First, the setup-action will download 1.22.0 (based on your go.mod go directive), afterwards go (version 1.22.0 you just downloaded) will download 1.22.5. This is because of your toolchain directive in your go.mod file.
Since 1.21 is the default go version on github hosted runners, I guess you could avoid downloading 1.22.0 and just rely on the toolchain directive. But I'm not 100% sure with that π€· At least, we could save a few seconds on CI π€
To summarize:
- The
godirective declares the minimum version now. Nothing more. - The
godirective should be a valid semver version. (major.minor.patch) - The toolchain is the go version that will be used to compile the module
Because this CLI project here is a "final end product" and not a module that others use, I guess you are fine by just using the go directive that uses always the latest go version.
Probably "no one" (assuption) depends on this project and therefore you might not need to declare any backward compatibily with others.
When you decide that, you might want to remove the toolchain directive. Why? Because starting with go 1.21, go will automatically download the version declared in the go directive. Without an toolchain, it will use automatically the go declared version as a toolchain version and hence download it.
So there is no need for this.
On the other side, if you think that other go projects depends on you, then it make sense to have both, go and toolchain.
While go should be "as low as possible", while the toolchain can be always be on the edge to enjoy bug fixes, faster compile time (assuming a greater go version is faster π
), new features, and a streamlined go version across developers (and CI).
What do you think? π€