For me, one of the reasons I disliked $GOPATH is that source code was not in $GOPATH; it was in `$GOPATH/src`.
The fact that they are very strongly against relative imports also didn't help, even if I get why they do it.
There are certainly nice things that the current Go module system buys; but one thing I miss is that under the old system, if one of the packages wasn't working the way you expected, the code was right there already; all you had to do was to go to that directory and start editing it, because it was already cloned and ready to go. The current thing where you have to clone the repo locally, add a "go.work" to replace just that package locally to do experimentation, and then remove the "go.work" afterwards isn't terrible, but it's just that extra bit of annoying busy-work.
But being able to downgrade by simply changing the version in go.mod is certainly a big improvement, as is having the hashes to make supply chain attacks more difficult.
1. Download the code (or update the copy you downloaded last time you had an issue)
2. Redirect `go build` to use the downloaded copy rather than the upstream copy (either by modifying go.mod or go.work)
3. Do the editing
4. Undo #2
Under the old system, you just had to do #3. And sure, it's not that much work, but it's a bit more than I had to do before.
(I'm the author of the linked-to entry. I wrote the entry because my impression is that a lot of modern Go programmers don't have this view of pre-module Go, and especially Go when you had to set $GOPATH and it was expected that you'd change it, instead of a default $HOME/go that you used almost all the time.)