> Package-Side Problems
> I also find it problematic because it breaks (in my mind) one of the most useful things about module names – they reflect the file path.

Sorry, this is incorrect: https://golang.org/ref/mod#module-path. A module path describes where to find it, starting with its _repository root_ (github.com, golang.org, etc) and then the subdirectory in the repository that the module is defined in (if not the root).

So, if a module lives in golang.org/username/reponame/go.mod, its module path is likely golang.org/username/reponame. If a module lives in golang.org/username/reponame/dirname/go.mod, its module path is likely golang.org/username/reponame/dirname. (and so on with a /v2 folder, etc)

I mention this because it appears that OP's major gripe in "package side problems" is that the /v2 dir "breaks" the (mis)conception that a module path describes _only_ the repo root.

(see also: multi module repositories)

> In other words, we should only increment major versions when making breaking changes

No, you can increment major versions whenever you want (though it's painful to your users). But, you _should_ increment a major version when you make a breaking change.

> I think a simple console warning would have been a better solution than forcing a cumbersome updating strategy on the community.

Could you elaborate on how a console warning solves the problem of users becoming broken when module authors make incompatible changes within a major version?

> Another problem on the client-side is that we don’t only need to update go.mod, but we actually need to grep through our codebase and change each import statement to point to the new major version:

What if you need to use v2 and v4 of golang.org/foo/bar? How would you import them both without one having a /v2 suffix and a /v4 suffix? Are you proposing that users should only be able to use one major version of a library at a time?

(I assume you are talking about a user upgrading to a new major, not the package author bumping to a new major. If the latter, a grep and replace is quite approachable and is shown in the blog you linked :) )

> Go makes updating major versions so cumbersome that in the majority of cases, we have opted to just increment minor versions when we should increment major versions.

I'm reminded of when the "unused imports not allowed" rule was lambasted, and then goimports was released and the conversation was snuffed out. This situation feels analagous.

You praise the toolchain and the good decisions in modules, but then hinge your thesis against it on "it's cumbersome". That's a valid concern, but it's likely that a tool that makes major version upgrades easier will resolve your issue. A wholly different design certainly is not needed .

Check out https://godoc.org/golang.org/x/exp/cmd/gorelease for one tool that's under development aimed at helping version bumps. It sounds like you also need something that will create the v2 branch/directory, change all the self-referencing import paths in that branch/directory, and change the go.mod path. That sounds like an easy tool to write - I expect something like that should come out quite quickly if it doesn't already exist.

-------------------

Side note: In my opinion, dependency management is a rat's nest of choices that seem good at the outset and end up with terrible consequences later on. Go modules make super well thought out decisions, and is a very very simple design, built to last for a long time without regrets. Sometimes the right answer is to work around a small problem with some tooling or documentation rather than go a totally different direction that will have large, sad consequences later.

That is: all choices have downsides, but it's good to choose the best choice whose downsides can largely be tackled with easy solutions like tools and docs. Decisions like "we should build a SAT solver" have sad, sad, sad consequences that can't be tool'd and doc'd away, for example.