7 ms·
I really liked using Go until I tried to publish a module with a version greater than 1. What kind of packaging system chokes on v2 of a module? What kind of
by na85 5y ago
I really liked using Go until I tried to publish a module with a version greater than 1.
What kind of packaging system chokes on v2 of a module? What kind of language recommends[0] with a straight face that you just duplicate your entire codebase into a v2/ subdirectory?
The module system is so obtuse and the documentation so poor that I will probably avoid go and choose other languages from now on. It really feels like they came to release time and someone in the meeting said "hey guys what if someone wants to release a new major version of their library?" and everyone else in the room had an "oh shit" moment because their amateur language design didn't address that corner case.
[0] https://go.dev/blog/v2-go-modules https://go.dev/blog/v2-go-modules
- sudhirj 5y agoThe reason I like this is because of one of the principles that Go espouses pretty heavily - never break backwards compatibility. If I install v1 of your package, I want it never to break. You can always improve performance, add more methods, etc, but the normal Go upgrade does not involve any code changes at all. The tools formalise that for modules as well, and encourage building a new module altogether if backwards compatibility is being broken. If it’s not being broken, it’s not a major version update, and major breaking updates are better off as new separate modules.
- grey-area 5y agoExcept in practice in all real software (including the go language!) minor and patch versions break importers all the time in small ways, AND major versions are usually used to indicate significant new features, not just breaking changes. So your claim is reduced to ‘I don’t want v1 to break my software in ways that the dependency finds important enough for a major version’. Not quite as reassuring is it? Plenty of security fixes and undefined behaviour fixes break importers all the time, and often importers and exporters disagree about the severity of that. Sticking with v1 will not save you that pain. I preferred the situation before where there was strong social pressure never to break the main branch.
- hsn915 5y agoThis is a cultural issue. It's not inevitable that by developing a module over time that you constantly break compability AND you want all people that depend on you to upgrade version. Go encourages the opposite approach. If your API is not stable, don't publish a package for public consumption, or, make sure to clearly mark it as unstable, so people know what to expect. One of the absolute best features of Go is stability. If I have a project written a few years ago, I can always run it against the latest Go compiler and know that it will still work. Why does this matter? I'll give you a counter example. In 2016 I wanted to work on a mobile application project and I just picked React Native because I heard it lets you easily create cross platform applications. I worked on it for a few weeks, then left it for about two or three months. When I tried to pick it up again, I installed the latest versions of node and npm and upgraded all packages. The project stopped working. I had no idea what went wrong. The error messages were obtuse and several layers deep. I tried to debug it for weeks to no avail. As a result, I abandoned the project and built just an Android version using Kotlin and Android Studio.
- grey-area 5y agoIt certainly is a cultural issue which is why it shouldn’t be enforced by tooling! I also completely agree about the value of stability, which is why I don’t like this change which paradoxically encourages more churn (normalises v2,v3 etc for breaking changes, normalises large breaking changes and rewriting apis). All APIs are slightly unstable in some sense (even adding fields can be a breaking change), so the aim should be to minimise version bloat and breaking changes and provide stability for importers, which the go language has done an amazing job at for the last decade. To give you a counter-example the sengrid api in go has had multiple large breaking changes/rewrites and has used this v2/v3 etc scheme. It’s still a horrible experience as an importer and I’d rather they remained stable instead of introducing massive churn with the cop-out that the old unsupported version didn’t change. In dependencies I import I want a perpetual v1 which doesn’t change over a decade and just slowly improves, not v31 - new improved rewrite this year! Which this rule explicitly encourages.
- 5y ago
- grey-area 5y agoYes this was a regrettable decision which causes lots of unnecessary pain and confusion and I wish they’d reverse it. You can just use tags, no need to copy files, but IMO it should not be the package management system’s job to enforce draconian rules about semantic versions and import paths. Otherwise go mod seems pretty straightforward and sensible to me though.
- throwaway894345 5y agoThis was just to support backwards compat with GOPATH for the brief time that the ecosystem was transitioning to modules. Now that GOPATH is rarely used, it’s not necessary.
- grey-area 5y agoI was talking about the requirement for v2/v3 in paths on major version as a regrettable decision, not the particular choice of duplicating dirs (which they recommended initially and as I pointed out can be sidestepped with a tag).
- throwaway894345 5y agoAh, my mistake.
- arghwhat 5y ago> What kind of language recommends[0] with a straight face that you just duplicate your entire codebase into a v2/ subdirectory? 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/3599f646293c1b0d381214ab26895abb9f605bc8/go.mod#L1 https://github.com/jackc/pgx/blob/3599f646293c1b0d381214ab26... A one-line change to your modfile and the import path is changed.
- cdogl 5y agoThanks for this informed comment. A timely reminder to me to read TFA, because I took parent comment at face value on first reading.
- nvarsj 5y agoThat'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.
- deleted 5y ago[deleted]
- atombender 5y agoIt 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.
- ruraljuror 5y agoMaybe 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?
- saturn_vk 5y agoIt looks like a subdirectory is obit recommended if you want to support get old versions of the toolchain. Using branches or tags is probably the way to go these days
- CraigJPerry 5y agoI'm on the other end of the spectrum for this one. Breaking changes in a stable library (i.e. has reached v1) should be totally avoided. Statically typed languages, fancy features like intellij's structural find and replace, they just don't cut the pain and annoyance of fixing an unexpected change in behaviour of a library in a large code base. It's just horrific drudge work, utterly unenjoyable, thoughtless labour that needs careful attention. The go module versioning is clearly designed by someone who has worked on a large many developer code base before. I can have V2 and V3 linked into my binary at the same time - a blessing for incremental refactoring.
- _ph_ 5y agoI think you have named the one good argument for this scheme: to allow a go module to exist in several versions in a project. Before the module system, this was just not possible. Which, in general, is a good idea. Programs today tend to have a too big dependency tree anyway, at least there should be only one copy of a module in the system. However, this is an idealistic view and depending on the number of dependencies, at some point it might not be possible to maintain this idea. npm on the other side goes totally crazy, every module import is local, you can have hundreds of copies of the same module in your system. The go module approach seems to be like a middle line. It puts a lot of pressure onto module maintainers not to break things within a major revision. They seem to be aware that this is not always guaranteed, that is why the module system not only tracks the major revision, but the exact subrevision of the module. But at least it can enforce, that changes which absolutely do break backwards compatibility are on differen major revisions. Of which you are allowed several inside your project.
- deleted 5y ago[deleted]
- avgcorrection 5y ago> and everyone else in the room had an "oh shit" moment because their amateur language design didn't address that corner case. I doubt that’s how it went down. They tend to be very confident in their design decisions. Whether that confidence is warranted or not.
- nvarsj 5y agoI've been a long time golang user and while I like to give the golang maintainers the benefit of the doubt, I have also struggled heavily with go modules. I think my main issue with it is that it does things implicitly without you telling it to. Running go commands will modify the go.mod file all the time, and this is largely invisible to you. As a result, your build is basically a moving target and seems to lose all reproducibility. It also makes the entire thing very opaque and hard to understand at times, since you need to understand the implementation details of go modules to fully know what's happening. In comparison, take godep. While not perfect, it simply did what I told it to, and only modified the dependency state when I gave it a command. This meant I knew exactly what was happening in my build system, and could update dependencies when I chose to. If anything, go modules is too smart for its own good... And I think this is a big problem for a build or packaging system. It needs to be explicit and simple. It's odd it was designed like this, given the language itself strives for these ideals.
- dcormier 5y agoI really like golang, and have used it for years. But I really dilike gomod. It's not uncommon for using it to be a frustrating experience. It makes me glad that most of my work these days is not in golang.