That's incorrect. The go blog recommends copying your entire project into a v2 folder. They do suggest you can use tags/branches instead, but it will cause problems with GOPATH projects.
It recommends this, sure, but there's no need for it. Doing so would be purely for backwards compatibility with older versions of Go tools that don't understand modules and rely on GOPATH. If you don't need to support older tools, then there's absolutely no need to copy anything.
Maybe I'm missing something, but I think there is a need. If your code imports dependencies A & B and they depend on C at two different versions, how can you handle this unless C is structured with versioned dirs?
Go does not map the module path directly to a file system path. You can import v1 and v2 at the same time because they have different module names. In other words, this is allowed:
$ go get github.com/linkedin/goavro@v1.0.5
$ go get github.com/linkedin/goavro/v2@v2.10.1
Then:
$ go list -m ... | grep goavro
github.com/linkedin/goavro v1.0.5
github.com/linkedin/goavro/v2 v2.10.1
Version 1 has a go.mod that declares:
module github.com/linkedin/goavro
and version 2 has a go.mod that declares:
module github.com/linkedin/goavro/v2
but both have their Go files located in the root of the repository.
Which is kind of remarkable. Python still seems to try to support every package manager and format that ever existed, and that’s part of why packaging in Python is so awful. Nice to see a language that can move forward with such a major change in such a short time and with relatively little pain.
Python3 is pretty close to Go in age and was a purposely compatibility breaking, so it could have easily changed things at that point and they definitely knew about the problem at that point.
The difference between 2 and 3 is way smaller than people make it out to be. I migrated a large Python 2.7 project to Python 3.8 and it wasn't a particularly painful experience. I feel that way more effort should have been directed at making 2 and 3 compatible.
It took more than a decade for the ecosystem to migrate. IIRC, a lot of effort went into making them compatible, but some things are just fundamentally incompatible and also very difficult to automate (e.g., string encodings).
I learnt Python in 2013, when Python 3 still had some serious growing pains. I switched from 2 to 3 almost overnight circa 2015 or 2016.
The last few years I cannot help but feel they were very close to making 2 and 3 play nice together, but the idea ironically lost traction because of how much Python 3 adoption had accelerated.
Go is pretty established. By the time this module change was made, a huge swath of the cloud ecosystem had been written in Go, including core components like Docker, Kubernetes, Terraform, etc. It’s also the default language for which Terraform and Kubernetes extensions are written, as well as the default language for container infrastructure (i.e., container runtimes, etc).
I think Python’s packaging story is a bummer in part because Python leans so hard on C which doesn’t have a standard build system or a sane approach to building or packaging.
Sure, and when it has been “pretty established” for a couple of decades, it’ll have a chance to have the community weight of important legacy projects that Python has.
This is a canned argument for any criticism of older programming languages.
First of all, it’s not much of a consolation to users that the packaging and performance are bad “because the language is old”, and secondly Python had already had half a dozen significant changes to its packaging format and ecosystem by the time it was Go’s age (distutils, cheeseshop/pypi, PEP241, setuptools, eggs, easy_install, etc).
Note that by this time, Python’s package management was far more complex than Go’s and it was also far more painful (and indeed, still is far more painful). Note that Go deprecated GOPATH when the language was already 9 years old, at a point when it was quite a lot older and more widely used than Python’s myriad package formats which are still supported today.
We can say “No fair! Go has the benefit of hindsight!” and true enough, but again as a user, I don’t much care—I just want the tool that’s going to solve my problem with the least headache.
And this isn’t even touching on the Python 2-3 saga, which began when Python 2 was merely 8 years old and lasted for more than a decade. If you want to argue that we should use the Python 1.0 release date for our comparison, then fine—call me in ~4 years if the Go ecosystem is on the precipice of a suite of breaking changes which constitute an existential crisis. My money says that wonky happen.
> This is a canned argument for any criticism of older programming languages
No, its a an argument that applies to the ease of making disruptive changes to languages with less legacy in the ecosystem (age is a factor, but not the only one; its also a reason why Ruby, which was a similar age with the disruptive 1.8 to 1.9 transition had an easier time than Python did with 2 -> 3).
It doesn't apply to all criticism, or even to “older languages” generally (at least not equally, though survivorship bias means it is likely at least somewhat applicable to older languages that it is interesting to discuss in the first place.)
Fair enough, but I don’t think we can argue that Go had considerably less “legacy” during its modules transition than Python had during its various package management iterations. I think Go is just quite a lot simpler than Python (or Ruby for that matter) especially in how it distributes software (just source code, minimal dependencies on C, etc) which makes package management a lot easier.
> A one-line change to your modfile and the import path is changed.
Another detail: since your import path change also affects internal imports between packages within your module, you also need to fixup a bunch of .go files in your repo (worst case all of them).
I still think it's not a big deal (it's all pretty straightforward non-magic). Just a small nitpick that it's not just one go.mod change.
"As long as they have users developing in GOPATH mode."
It's documentation written when GOPATH was still a widely used for development.
I think nowadays it's less of a concern to have a module first code base with GOPATH unsupported. It's nicer to use a V2 branch. Or delegate V1 to a V1 branch and maintain V2 in master.
I’m not disputing that things may have changed since the post was written. But the comment I responded to claimed that the linked post didn’t recommend copy-into-subdirectory, which it clearly does.
How is a branch nicer than a subdirectory? Off the top of my head, it seems like backporting bugfixes might be easier using a branch (if you're lucky, you can just cherrypick the commit and it will work) - any other reasons?
Not Go at least. You misunderstood the post completely.
Here is an example of how you are supposed to change the import path for subsequent major versions (that is, backwards incompatible versions): https://github.com/jackc/pgx/blob/3599f646293c1b0d381214ab26...
A one-line change to your modfile and the import path is changed.