[HN Gopher] Keeping your Go modules compatible ___________________________________________________________________ Keeping your Go modules compatible Author : stargrave Score : 88 points Date : 2020-07-07 17:15 UTC (5 hours ago) (HTM) web link (blog.golang.org) (TXT) w3m dump (blog.golang.org) | poorman wrote: | > When you run into a case where you want to add a method to an | existing interface, you may be able to follow this strategy. | Start by creating a new interface with your new method, or | identify an existing interface with the new method. Next, | identify the relevant functions that need to support it, type | check for the second interface, and add code that uses it. | | I like this pattern, and I have used it. The issue I have is when | I look at the generated godoc, the original interface is in the | signature. I don't know the function accepts the new interface as | well without either digging into the code or a comment for the | function. | candiddevmike wrote: | Reading these blog posts, you get see Go's simplicity start to | unravel with modules. Uncomparable structs? Type checking | workarounds? You start to wonder if these bandaids would be | necessary in a generics world. | | For the record, I'm indifferent on the chosen module solution | being right or wrong. My ideal module tool is something like npm, | but it shows me the impact: diff the module changes, look at my | code, and tell me what's impacted by the upgrade. Giving | developers more information when upgrading libraries will go a | long way towards making "update your libraries" a regular | housekeeping task. | merb wrote: | btw. this blog is about binary/source compatibility, which is a | fucking hard problem in nearly EVERY language. (maybe not in | javascript tough) | Ericson2314 wrote: | Gah in every language I want that interface comparison tool, | and I keep on being disappointed. | Ar-Curunir wrote: | rust-semverver does what you want for Rust, I think? | jbamsterdam wrote: | Until gorelease is ready, you can try apidiff (https://go.goo | glesource.com/exp/+/refs/heads/master/cmd/apid...). | jrockway wrote: | Modules have nothing to do with comparable structs. It's just | that making a comparable struct uncomparable could break users | of your API, so it's something to be on the lookout for if you | value backcompat. (The module system ensures that users will | get the version of the code they want; you only have to worry | about backwards compatibility if you expect users to upgrade to | your new version.) | | There are millions of ways to break users with an update that | machines can't detect. For example: | | Old version: | | func Lt(a, b YourType) bool { return a < b } | | New version: | | func Lt(a, b YourType) bool { return a >= b } | | This is not specific to Go. | jbamsterdam wrote: | Despite the title, the problems that this article discusses | could have happened even before modules were introduced. Before | modules, your only choices were to stay compatible or break | users. Modules give us the freedom to make breaking changes in | a safe, documented way. | mseepgood wrote: | > Reading these blog posts, you get see Go's simplicity start | to unravel with modules. Uncomparable structs? Type checking | workarounds? You start to wonder if these bandaids would be | necessary in a generics world. | | Nothing of this has to do with or would be better with | generics. | naringas wrote: | there's something that I just don't get about golang modules, I | don't know what it is but they don't click with me | | it might well be something tacit that golangers learn from each | other directly? or otherwise it's so obvious and simple and I | just haven't realized? | | it feels like it's the kind of thing that just clicks one day | possibly after a few years | ArmandGrillet wrote: | IMO the documentation isn't there yet, it lacks a Q&A webpage | or something short and giving the main how-tos in a succinct | manner: How to create a module? How to bump a package version? | How to use a specific package's branch? What to do if there is | a conflict because a package used by another package messed up | its compatibility? | | The current first Google result when looking for "go modules" | is https://blog.golang.org/using-go-modules which is a very | verbose post starting with "This post is part 1 in a series of | 5 parts". Not very engaging. | | In one year I've accumulated a few snippets that I use | regularly and get used to `go mod` but it was painful at the | beginning. I wish I could have contributed to this topic but Go | is most of the time a language that only requires to read | pkg.go.dev and the main blog posts to know what's next and this | Go modules workflow is, like gopls, something that doesn't | currently have a good place to be documented AFAIK. | | Edit: Thaxll's comment gives a very nice URL to learn about Go | modules, still too much for a beginner IMHO but it has a Q&A | part that goes very deep. | [deleted] | m0th87 wrote: | You're not alone. I've been writing go since before 1.0, and | can handle modules/packages in _any other language_ fine, yet | go's regularly leaves me stumped. | | A little while ago we were hitting yet another issue with | dependencies related to version pinning at work. I tried to | divine what the disparate versions mean, and came up with this | flow chart from a legalistic reading of stack overflow issues | [1] and the go modules doc [2]: has the package | opted into go modules (i.e. is there a go.mod?) yes | does the repository use semver? yes | is the major version <= 1? yes | => normal versioning, e.g. github.com/stretchr/testify v1.3.0 | no => when importing, we need add /vN at the | end, e.g., import "github.com/my/mod/v4", and in go.mod it will | behave like github.com/my/mod/v4 v4.1.0 no | => pseudo-versioning will be used, e.g. github.com/kolo/xmlrpc | v0.0.0-20190717152603-07c4ee3fd181 no does | the repository use semver? yes is the | major version <= 1? yes => | pseudo-versioning will be used, e.g. github.com/kolo/xmlrpc | v0.0.0-20190717152603-07c4ee3fd181 no | => version will be marked as incompatible, e.g. | github.com/zeromq/goczmq v4.1.0+incompatible no | => ??? | | I still don't know if this is right. But that's not really the | point. I think the go authors painted themselves into a corner | with such an anemic initial release. Now that they're trying to | address shortcomings, the complexity is blowing up to handle | the very large/diverse ecosystem. It reminds me a lot of java | around 1.4 when they added in generics. In the long-run it was | the right move, but man was it painful. | | 1: https://stackoverflow.com/a/57372286 2: | https://github.com/golang/go/wiki/Modules | fourseventy wrote: | I agree. I used godep before and I thought it was intuitive and | had no issues with it. But I still struggle with gomodules | Thaxll wrote: | It's pretty clear and well explained there: | https://github.com/golang/go/wiki/Modules | | On a day to day operation, you need to know 2/3 commands that's | it. | | - go mod init | | - go mod tidy | | - go get xxx | opqpo wrote: | Go modules and the entire package management and versioning | system is just embarrassingly horrible. It looks like it was | designed by people who have no background in software engineering | at all. The language as a whole despite being now universally | used as the backbone of cloud native, it honestly looks like it's | intentionally designed to be horrible and insulting for anyone | with sensible mind. Every obvious right decision looks like it's | intentionally being replaced by a bad one if it's the right path | is easier. | hinkley wrote: | Something I knew starting out, forgot, and learned again, is | that there's a huge liability to spending your entire career | working for one company. | | There will be things they do so well they aren't even on your | radar, and you will have a huge blindspot there. And there are | things they tolerate that pretty much nobody else will. So you | will either suffer in ignorance or learn some nasty, nasty | habits. | | Without moving you see no diversity, and without seeing | diversity you shouldn't be put in charge of building _anything_ | for 'everyone'. You are only qualified for niche solutions, | which unfortunately outsiders might not clue in on until | they've invested heavily in your ideas. | Jtsummers wrote: | In college we referred to this same idea (among my peers who | were going on through graduate studies, particularly PhDs) as | "academic incest", where you aren't sufficiently exposed to a | diverse enough set of ideas and end up too narrowly focused | or clouded in your judgment. | | Ways to overcome it include: moving (in academics, accepting | a fellowship at other institutions; as a professional, change | jobs); observation (keeping abreast of the latest trends | outside your immediate environment and field); community | participation (attending conferences, symposia, and similar | things; or even forums like this). | | But ultimately it requires a recognition that your views, | knowledge, and beliefs are, necessarily, constrained by your | experiences and that you sometimes have to seek out novel | experiences or the experiences of others to change yourself. | If you lack the drive for either, or too great a confidence | in your own present state, then you're going to be stuck. | Ericson2314 wrote: | That's true, but Google is big and they use many languages, | and the amount of ignorance needed to make Go cannot be | explained by that alone. | mseepgood wrote: | > Go modules and the entire package management and versioning | system is just embarrassingly horrible. It looks like it was | designed by people who have no background in software | engineering at all. | | Go modules is probably the most well-wrought versioning system | for a programming language. The amount of thought that went | into it is insane. | | https://research.swtch.com/vgo | littlestymaar wrote: | It's the most _over-though_ versioning system ever actually. | It 's a rare mixture of NIH syndrome and obsession to a | specific theoretical concern. Yes semver dependency | management is NP-hard[1], but lawn mowing is NP-hard too, and | yet that doesn't seem to stop anyone else! | | [1] in fact it's only NP-hard if you add an optional | aditionnal constraint: that every dependency must have a | single instance even if it's a transitive dependency from | several dependencies with conflicting requirements. If you | allow different major version of the same dependency to | coexist in the dependency tree, it becomes a straightforward | linear problem while still behaving like every single other | package manager in existence for the end-user. Now that's a | well thought system! (And there at least one language, pretty | popular these days on Hacker News, which does exactly this) | LukeShu wrote: | Go does allow coexisting major versions, just not | coexisting minor versions. | jacques_chester wrote: | Go mod is a gigantic pig's breakfast. It would work _OK_ if | everyone was on it already, but everyone is _not_ on it | already. | | If I took a survey of every go.mod file and looked at the | versions, more than half would still be that absurd, un- | eyeballable, merge-review-hostile, another-arbitrary-c- | hacker-mini-language, shas-upon-shas version string that the | "insane amount of thought" landed on because it assumes | everyone is already conformant. The ugly corner case for | "unversioned" dependencies is the _main_ case. | | The "insane amount of thought", as is the norm for the Golang | team, involved a gymnastic demonstration to evade (1) any | serious consideration of prior art _in use_ whatsoever, and | (2) entertaining not even the slightest concept of how shitty | it would be to impose massive externalities on everyone else. | | Even an apologetic tone would have made the pill less bitter. | Or better yet, blessing godep. Or copying Maven wholesale. Or | Bundler. I don't care, because what happened has vapourised | millions of developer hours chasing down completely | unnecessary versioning issues. | ithkuil wrote: | It's a delicious breakfast but, served for dinner. | | I love the mechanics of it. Most of what you describe is | the result of having waited ages before implementing it, | and the resulting prolonged migration period, exacerbated | by the relatively decent (but not perfect) backward | compatibility with pre-modules code. | | Prior art isn't perfect either: I'm happy somebody tried | something different from centralized naming systems or | almost-but-not-quite federated artifact collections (such | as the various maven repos). There is already a global | system to get hold to unique names: the domain name system. | For better or worse, that's a solved problem, let's not | create new naming arbiters | jacques_chester wrote: | > _Most of what you describe is the result of having | waited ages before implementing it_ | | Except we already had godep. It worked. It was in | widespread use. | | > _exacerbated by the relatively decent (but not perfect) | backward compatibility with pre-modules code._ | | My experience has been that the backwards compatibility | has been a nightmare. It forces itself on any downstream | repository, whether or not that repository wishes to | participate. Plus it does very poorly on diamond | dependencies, giving error messages about as scrutable as | the I Ching. If your answer is "they're doing it wrong", | take it up with the Kubernetes and go-client maintainers, | because I can't change what they are doing. | | > _There is already a global system to get hold to unique | names: the domain name system. For better or worse, that | 's a solved problem, let's not create new naming | arbiters_ | | Versions are not addresses. Addresses are not versions. | You may find a version _at_ an address, but addresses are | not versions. Docker did the same thing with image | references and they too created a pig 's breakfast. The | difference was that they didn't have prior art to compare | to and it was an oversight obvious largely in hindsight. | I do not extend the same credit to Russ Cox. | ithkuil wrote: | > Except we already had godep. It worked. It was in | widespread use. | | > un-eyeballable, merge-review-hostile, another- | arbitrary-c-hacker-mini-language, shas-upon-shas version | | godep shared the same problem. We can argue that godep | was good enough and the Go maintainers handled the | situation poorly with this whole "ask community and then | ignore the community" trick. But you're focusing on the | transition; if this system had been part of Go 1.0, I | would have had nothing bad to say about it. | | I'm not arguing the the transition process wasn't a mess. | I'm arguing that it became a mess precisely because they | wanted to attempt backward compat. They could have said | "this is go 2; if you want to use your library with go 2 | you have to use this standard, tag your release, or | upload it to some central index" | jbamsterdam wrote: | Do you have any specific examples in mind? ___________________________________________________________________ (page generated 2020-07-07 23:00 UTC)