Yep, unfortunately this concern was mostly shrugged off by the Go team when it was brought up (because it would've required a lot of work to fix IIRC, which I think is a bad excuse for such a problem). IMO, a `go tool` dependency should've worked exactly the same way that doing `go install ...` works with a specific @tag: it should resolve the dependencies for that tool completely independently. Because it doesn't, you really, really shouldn't use this mechanism for things like golangci-lint, unfortunately. In fact, I honestly just recommend not using it at all...
No, it really is a problem with this design and not an issue with golangci-lint.
The trouble is that MVS will happen across all of your dependencies, including direct and other tool dependencies. If everything very strictly followed Go's own versioning guidelines, then this would be OK since any breaking change would be forced off into a separate module identity. However, even Google's own modules don't always follow this rule, so in reality it's just kind of unrealistic.
You don't need something huge like golangci-lint to run into problems. It's just easier to see it happen because the large number of dependencies makes it a lot more likely.
As long as a team agrees to have .golangci-version as the source of truth, the people using the tool don't have to worry about having the right version installed, as the wrapper fetches it on demand.
Having the wrong version installed between collaborators is problematic as then they may get different results and spend time wondering why.
Interesting - would something like `make lint` (which then installs to `$PWD/bin`) work? That's how I've been doing it on the projects I've been working on, and it's worked nicely - including automated updates via Renovate (https://www.jvt.me/posts/2022/12/15/renovate-golangci-lint/)
A simpler approach is to use `go run` with a specific version. e.g.:
go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.63.4 run
Easy enough to stuff in a Makefile or whatever.
Even better in Go 1.24 since according to this article the invocations of go run will also be cached (rather than just utilizing the compilation cache.) So there shouldn't be much of an advantage to pre-emptively installing binaries anymore versus just go running them.