[HN Gopher] Go's major versioning sucks - From a fanboy
___________________________________________________________________
Go's major versioning sucks - From a fanboy
Author : wagslane
Score : 91 points
Date : 2022-03-04 17:39 UTC (5 hours ago)
(HTM) web link (wagslane.dev)
(TXT) w3m dump (wagslane.dev)
| dilatedmind wrote:
| Thoughts on a couple of your points:
|
| - we don't need any kind of backwards compatibility, we just
| update everything.
|
| if you don't care about backwards compatibility, then you can
| stay on v1 forever. Have you considered a monorepo? That would
| simplify updating packages and give you the behavior you want.
|
| - For the client to update, it's not a simple path change in
| go.mod
|
| if a package moves from v1 to v2, there are breaking changes in
| either api or behavior. I think this implies more than a simple
| change to go.mod. This also allows importing both versions of a
| package if necessary.
| dmitriid wrote:
| > there are breaking changes in either api or behavior.
|
| So instead off focusing on those changes I have to first fix
| potential dozens of files for no reason at all.
| bww wrote:
| I've taken to just making /v0 or /v1 the root of every package I
| maintain. Even though it's not required I think it's a good
| practice.
|
| It doesn't affect the package name (unless you choose to), only
| the import path. So it eliminates any ambiguity about the
| interface you intend to use and it only affects import
| statements. Personally I think that's a good balance.
| jmyeet wrote:
| I like Go but Go has made some serious misteps (IMHO), which the
| author touches on. Dependency management in Go is so _incredibly
| bad_ it 's hard to fathom. Did no one on the early design team
| ever deal with depenencies? Java is so much better here and came
| years earlier. Go would've been so much better had they just
| copied any of the Java options from Day One.
|
| So this versioning thing is just weird and I agree with the
| author. It's a strange thing to have opinions on and an even
| stranger opinion to have on that thing.
|
| But the thing that gets me is the whole putting
| "github.com/username/module" into code is just awful.
| philosopher1234 wrote:
| This comment is empty of content. All you've said is "go is
| bad" over and over again. Who would be persuaded by this?
| jrockway wrote:
| I disagree with all of this. Go's package management system is
| a breath of fresh air compared to all other languages. Nobody
| ever has any problem grabbing dependencies. There is only one
| way to do it and it's built into the language runtime; if you
| have Go installed you can install the modules. Other
| applications on your system can, with no effort (virtualenv,
| etc.) use different versions of those modules. Dependency
| installation can't print messages to my terminal.
|
| It's a joy.
|
| Importing modules from a particular URL is a great way to
| handle them. No central server required! Everyone can name
| their module "utility utils" or whatever. And, nobody is
| forcing you to use Github to host your modules, you can put
| them on any web server you control and import them as
| example.com/your-thing. Decentralized. Easy to use.
|
| If I had two complaints, they would be:
|
| 1) Library authors that think "replace" directives propagate up
| to consumers. They do not. They are ignored when you depend on
| the module. If you depend on one of these libraries and want
| the workaround that the author has smoothed over with a
| "replace" directive, you have to copy that directive to your
| own go.mod.
|
| 2) Library authors that distribute one go module for their
| super-complicated server and their super-simple client. This
| results in unnecessary dependency explosion. (Loki 1.x was an
| example of this pattern. Their server depends on things like
| Kubernetes, where their client only depends on net/http. But if
| you naively import their client, suddenly your project depends
| on Kubernetes.)
|
| (2a would be no concept of test-only modules. Some modules are
| only needed for the tests; it would be nice to not propagate
| these up to consumers. It isn't an actual problem, though, just
| a "would be kind of nice" or "I could see why they did that" if
| it existed.)
|
| Neither of these are Go issues, just maintainer issues that can
| happen with any language.
| zht wrote:
| sorry is github.com/username/module is much worse than
|
| com.arbitrary.x.y.z ?
| tkiolp4 wrote:
| In the source file one could just say
| import "username/module"
|
| And in the go.mod file the whole URL can stay
| require github.com/username/module v1.2.3
|
| I only see advantages with this approach and I imagine it's a
| rather "easy to add" feature that can be even backwards
| compatible.
| philosopher1234 wrote:
| What if I publish gitlab.com/username/module and i dont
| know anything about your github project? This seems like a
| pretty obvious disadvantage, so its surprising you failed
| to see it. What are the advantages?
| didip wrote:
| I absolutely disagree with everything said here.
|
| Maven naming convention is absolutely atrocious. And don't tell
| me that naming convention is optional. To be part of Java
| ecosystem Maven naming convention is a requirement.
| dmitriid wrote:
| Additionally, `go build` fails when there's a major version
| mismatch and the error is obtuse, contains no good info on what
| the user should do
| kstenerud wrote:
| I just keep all my go project major versions at 1, then use the
| second number as "major" and the third number as "minor".
| Anything incompatible increments major, anything compatible
| increments minor.
|
| This avoids all that v2, v3, v4 "nanny knows best" nonsense.
| mfcl wrote:
| Why not v0 instead? It's better suited for that purpose.
| maxmcd wrote:
| Your users are going to have a bad time if they ever import two
| different libraries that both depend on different fake "major"
| versions of your library. The newer of the two will be
| selected, and any incompatibility that the different libraries
| are not prepared to handle will break things.
| paskozdilar wrote:
| What purpose does that serve?
|
| Unless your version numbers signify something to the user, you
| might as well just use incremental integers - v1, v2, v3, etc.
| pgwhalen wrote:
| This is a comment on an article about Go package management,
| which enforces that packages a versioned with a semver-esque
| string.
| paskozdilar wrote:
| Your point being?
| pgwhalen wrote:
| v1, v2, v3 are not valid module versions in Go, so it
| requires a slightly different solution.
| paskozdilar wrote:
| If you're not distributing your Go package to others as a
| library, then you don't need to follow the Go module
| versions. They are only enforced user-side.
| pgwhalen wrote:
| True, though if you have code in separate repositories
| you might want to stick to _some_ versioning scheme to
| use the module tooling to your advantage.
| icholy wrote:
| I wrote a tool that automates: - discovering
| new major versions in your go.mod (gomajor list) -
| switching between major dependency versions. (gomajor get)
| - updating the major version of your own module. (gomajor path)
|
| https://github.com/icholy/gomajor
|
| It's not perfect, but it takes a lot of toil out of working with
| SIV.
| iandinwoodie wrote:
| SIV = Semantic Import Versioning [0]
|
| 0. https://github.com/golang/go/issues/44550
| paskozdilar wrote:
| >I agree with the sentiment that we should only increment major
| versions when making breaking changes, but more often than not
| breaking changes are really easy to accommodate for.
|
| Maybe on a small scale breaking changes don't cause issues, but
| in large-scale development, you simply can't afford to have a
| bunch of random CI/CD pipelines fail because a developer decided
| to "accommodate for" a backwards-incompatible change without
| separating it to a new import path.
|
| >Using different paths for different major versions makes more
| sense in situations where we may require two different versions
| of the same package, you know, diamond imports and all that. This
| is the exception, not the rule, and it seems strange to tap dance
| around a problem that doesn't exist in most codebases.
|
| Diamond imports are not as rare as you think - it's just that you
| never run into it in your own code, but in the code of your
| dependencies. And in Go, the problem is already solved for you so
| you never even see the solution at work.
|
| Let's say you use two libraries for, say, backend and frontend -
| libbackend and libfrontend. Let's say they both depend on some
| parser library, say libparser, version 1.0.
|
| Now assume that libbackend upgrades the libparser dependency to
| 2.0, but the import path stays the same and your application -
| the one that has been successfully auto-updated on a CI/CD server
| for years and nobody remembers how it works anymore - breaks, and
| you have no idea why, compiler reports some weird API-
| incompatibility errors, and now you have to spend two weeks
| getting back into the codebase and debugging the issue, until you
| realize you can't really fix it, because the guy developing the
| language decided that diamond imports are "a problem that doesn't
| exist in most codebases".
| jchw wrote:
| Honestly, my only complaint about go mod major versioning is
| just how unintuitive versions after v1 are. While some may
| disagree about the tradeoffs, I think the reasoning behind it
| is totally solid, but there are definitely valid complaints
| about the exact behavior of modules being somewhat confusing. I
| recall confusion with trying to update a library with no tagged
| versions, too, for example.
|
| That said, I think people greatly undersell how well Go has
| done packaging. There's, again, tradeoffs that are at least
| arguable; but, I hate when people say things like "Didn't
| (npm|apt|cargo|...) already solve this?" Honestly, often times
| the answer is at best "kind of?" -- a lot of these packaging
| and versioning problems remain without complete solutions.
| Meanwhile, Go has some novel design choices that set it apart.
| The module proxy is a slightly unfortunate tradeoff, but Go
| remains one of the only languages with a good story for mostly
| decentralized package management. The module proxy is more of a
| hack that gets you some of the advantages of centralization
| without strictly depending on it. But beneath that, it's nice
| that you can pull packages from basically anywhere with several
| VCSes.
| tikkabhuna wrote:
| It would be great to be able to declare a dependency with an
| alias at the go.mod level. Rather than requiring the publisher
| of a dependency to update their paths you can choose.
|
| That way if a dependency does a minor upgrade that breaks your
| code but you also need some new functionality, you could depend
| on the old code in a particular package and new code in
| another.
| cube2222 wrote:
| > Due to our size, we don't need any kind of backwards
| compatibility, we just update everything.
|
| Then just use 0.y.z versions and be done with it?
|
| If the library constantly changes and everybody expects that,
| then that seems fitting.
|
| I like Go's major version handling very much. If it's backwards
| incompatible, it's basically a new library under the same name
| and development team.
|
| In my opinion making major version updates so painful also
| incentivizes not making backwards incompatible changes in
| libraries, which results in the Go ecosystem being very stable
| overall (something I value a lot in my day-to-day).
| paskozdilar wrote:
| >If it's backwards incompatible, it's basically a new library
| under the same name and development team.
|
| This, this, and a hundred more times this.
|
| Incompatible is incompatible. There is no "kinda incompatible",
| "99% compatible" - when it comes to dependencies, they either
| work properly or they don't.
|
| Software should be eternal. Without being strict about semantic
| versioning, it is impossible to make it so.
| pcwalton wrote:
| Well, that's clearly not the way Go operates. Go makes
| incompatible changes between minor releases; they just don't
| break _type signatures_. For example, debug /pe
| ImportedLibraries(), which is supposed to return all the
| libraries that a module imports, was stubbed out to return
| "nil, nil" in a minor release [1]. This is clearly an
| incompatible change, but as it didn't cause code to fail to
| compile the Go team deemed it semver compatible.
|
| Edit: Apparently this is wrong! See replies below.
|
| [1]: https://fasterthanli.me/articles/abstracting-away-
| correctnes...
| slrz wrote:
| _For example, debug /pe ImportedLibraries(), which is
| supposed to return all the libraries that a module imports,
| was stubbed out to return "nil, nil" in a minor release
| [1]_
|
| I just looked at the Git history and this is plain false.
| It already looked that way when the big source tree move
| (src/pkg/ -> src/) was done in 2014. Tracing it back
| further (to before Go 1.0 times, when there wasn't even a
| builtin error interface yet and the function returned
| os.Error), ImportedLibraries was *never* implemented in
| debug/pe.
| philosopher1234 wrote:
| I think taking a highly abstract definition of backcompat
| is not useful. We need a practical definition of back
| compat. If there are no (or effectively no) downstream
| consequences of a change, it is clearly backcompat. If
| there are some downstream consequences, you get into
| judgment call territory, but it still may be worth it. We
| cannot create a perfect universal rule here, and Amos is a
| fool for holding that standard so rigidly.
| pipe_connector wrote:
| It's worth noting that the author of that article was
| mistaken, there was likely some other issue with their
| software than what they described here. ImportedLibraries()
| in the pe package has never done anything other than
| returned nil, nil. This wasn't changed in a minor release.
| You can browse the source history here: https://github.com/
| golang/go/blame/master/src/debug/pe/file....
| slaymaker1907 wrote:
| No, it really shouldn't be. It makes it impossible to
| distinguish between those "theoretically this a breaking
| change" kind of changes and the "you're going to need to
| rewrite a bunch of code" kind of changes. At the very least
| libraries should be allowed to define how the library must be
| used in order for their semantic versioning to apply. For
| languages which allow "import * from x" style imports, the
| library should still be allowed to add in new functions
| without that being a breaking change.
|
| If you want your software to be pristine forever, you really
| need to pin your dependencies, ideally via copying the source
| of the library into your repo so you aren't reliant on a
| package manager being available in the future. For library
| developers, regardless of versioning scheme you need to avoid
| ANY breaking changes whatsoever. Instead of changing an
| existing function, introduce a new one so that your
| downstream users can still access the old behavior while
| keeping up to date. Trust me when I say this will be much
| easier most of the time than patching old versions with
| security updates and bug fixes.
| paskozdilar wrote:
| API is API. Either a library implements it or not. There is
| no room for "just this small API change uwu" in large-scale
| development.
| slimsag wrote:
| How do you define "compatible"? Semver doesn't define it.
|
| An HTTP server can remain API compatible, and still drop or
| break support for a major feature you care about. Surely you
| don't want that to ship in a patch release.
|
| Adding a new struct field, even a private one, can break API
| compatibility in Go if people use your struct without named
| fields. Do you want a new library in this case or not?
|
| Semver doesn't cover CLI compatibility, either, do you want a
| CLI redesign to remain v1 or become v2?
|
| Nuance matters. Stating to "just be strict about semantic
| versioning" doesn't help, semver is fuzzy.
| pgwhalen wrote:
| This is a good point, arguably even fixing any bug breaks
| compatibility, at least if you're a kernel maintainer. An
| (in)famous Linus quote: If a change
| results in user programs breaking, it's a bug in the
| kernel. We never EVER blame the user programs.
| slaymaker1907 wrote:
| I don't think this is all that useful of a quote outside
| of operating systems (and even there I still find it of
| questionable value). You really need to define how people
| can use your software (at least at a high level) and
| receive backwards compatibility guarantees.
|
| Even in the Linux example, kernel modules do not receive
| compatibility guarantees because it is difficult to keep.
| You may need to rewrite your module depending on how it
| is written when upgrading the kernel. It also doesn't
| apply in case of security vulnerabilities and certain
| classes of bugs. Technically viruses can be user programs
| which rely on those vulnerabilities and even excluding
| those, there are cases where some API seems benign but
| later turns out to be flawed (like precise timers in the
| context of browsers).
| noctune wrote:
| I think it's a difference in what one considers to be
| "the API". Linux is very much to the de facto API side,
| whereas some other project might be more one the de jure
| API side with a rigid specification and allowing any
| change within that. Most things are probably somewhere
| between the two.
| paskozdilar wrote:
| > How do you define "compatible"?
|
| I define it as "provides the equivalent API".
| viraptor wrote:
| There's an extra dimension here though - support. Projects
| don't have unlimited resources which in majority of the cases
| means that only one major version is live.
|
| For downstream consumers that gives 2 options: get stuck on
| an old version silently sometimes, or deal with an occasional
| breakage during usual dependencies updates. If the old
| version is used for talking to some external service, you
| will break one day.
| Groxx wrote:
| There absolutely is fuzziness in incompatibility.
|
| I can change one part of an API and leave another untouched -
| that's part compatible, part incompatible. It's only an issue
| if you used the changed part.
|
| (If you think that first one always counts... what if the
| changed part is literally called
| YouMustNotUseThisFunctionOrYourCodeWillAlwaysBreak() ? It's
| clearly implied to not be part of your _intended_ API,
| despite technically being part of it.)
|
| I can add something to a type, in a way that's backwards
| compatible at compile time... but common reflection patterns
| might cause everyone's code to explode.
|
| I can make a change that solves a bug that someone was
| accidentally relying on by doing the wrong thing, but doesn't
| affect compile-time behavior, nor runtime for anyone using
| the library the way they should. But that bug-user's code is
| now broken, is this an incompatible change?
| paskozdilar wrote:
| > I can change one part of an API and leave another
| untouched - that's part compatible, part incompatible. It's
| only an issue if you used the changed part.
|
| When you commit to a version 1, you assume that every user
| of the package is using every feature you provide through
| your official API. If you break any slightest piece of the
| API, you've broken compatibility. It might "kinda work" for
| many users, but it will almost surely cause significant
| pain for many others.
|
| > I can make a change that solves a bug that someone was
| accidentally relying on by doing the wrong thing, but
| doesn't affect compile-time behavior, nor runtime for
| anyone using the library the way they should. But that bug-
| user's code is now broken, is this an incompatible change?
|
| It is not an incompatible change, and it is the
| responsibility of the bug-user's code to fix the bug in his
| program.
|
| Of course, when such a thing happens on a large-enough
| scale, the API developer sometimes cannot afford to "fix"
| the behavior and force countless users to fix their
| programs, so the quirk just becomes de-facto part of the
| API.
| ithkuil wrote:
| > I can make a change that solves a bug that someone was
| accidentally relying on by doing the wrong thing ...
|
| There is even a "law" for that: https://www.hyrumslaw.com/
| mftb wrote:
| This is the answer. It's all internal, he says in his case.
| They know what they're doing with their own stuff. Staying on
| v0 is just another signifier that it's one of their internal
| things, they need to handle specially.
| bborud wrote:
| > Then just use 0.y.z versions and be done with it?
|
| Yeah, that would work, except a lot of people read 0.x.y
| versions as "alpha quality". Regardless of the actual code
| quality.
| pgwhalen wrote:
| Is this a problem inside a small company though? I would
| expect there to be much better signals about how alpha-ish a
| library is in that setting (i.e. talking to your coworkers).
| bborud wrote:
| Funny you should ask. Yes, it can be when you use third
| party software and people have version number hangups.
| pgwhalen wrote:
| Version number hangups are indeed a problem, I don't mean
| to suggest my organization has escaped them. But if you
| can wade through those successfully, the technical
| solution itself often does make sense.
| gowld wrote:
| If you expect a certain version to be valuable long term,
| promote it to Z.0 version. It's OK to to have
| AwesomeButRapidlyChangingLibrary-2022.03.0 branched from
| 0.y.z.
| bborud wrote:
| Or, as some people recommend, skip directly to V2 as the
| first version.
| philosopher1234 wrote:
| This is true and unfortunate, but I think the engineering
| value of meaningful versions is important and I expect that
| with enough time people will adapt to understanding a
| different meaning of 0.x.
|
| And besides, people are right to understand 0.x is risky b.c
| you are not guaranteeing backwards compatibility.
| digisign wrote:
| If it is changing all the time, then it is "alpha quality."
| pgwhalen wrote:
| >> Due to our size, we don't need any kind of backwards
| compatibility, we just update everything.
|
| > Then just use 0.y.z versions and be done with it?
|
| FWIW, I also work in an organization that thinks of libraries
| this way, and we've found success and simplicity in versioning
| (for production) our Go libraries as 0.X.0 where X is just a
| monotonically increasing number generated by the build
| pipeline.
| mananaysiempre wrote:
| ... Zerover[1]?
|
| [1] https://news.ycombinator.com/item?id=28154187
| pgwhalen wrote:
| Yep! I think it's fair to needle open source software, but
| it absolutely makes sense for a lot of internal development
| to adopt this sort of versioning policy.
| earthboundkid wrote:
| > This means major version changes are a fairly regular
| occurrence. Some say that we should just stay on v0, and that's a
| reasonable solution. The problem is these ARE production packages
| that are being used by a wide number of services. We want to
| Semver.
|
| This is a lame problem. v0.Major.Minor-Patch. Done. Yes, semver
| includes an optional dash for a fourth parameter, and Go supports
| it.
| pa7ch wrote:
| How does the forth parameter affect version ordering though?
| Since its a pre-release I would assume v0.1.2-3 actually comes
| before v0.1.2. You'd have to ensure make all your versions have
| the dash I guess.
| munificent wrote:
| _> Since its a pre-release I would assume v0.1.2-3 actually
| comes before v0.1.2._
|
| That's correct.
|
| (The really fun weird corner of semver is build suffixes.
| According to semver 2.0.0, v1.2.3+4 and v1.2.3+5 have no
| specified relative ordering. According to semver 2.0.0-rc.1,
| build suffixes are ordered.)
| henvic wrote:
| I recognize that this might be a PITA, but for me there is no
| easy way out of problems related to major versioning, and the
| clear answer is sticking with version 0.x.x for a considerate
| amount of time.
|
| It seems people rush to publish version 1.0 (or 2.0, etc.) of
| their libraries, when they'd be better off just sticking with
| version 0.x.
|
| It's not like that a package isn't ready for production because
| it is < 1.0. It might as well be. If you're an early adopter, I'd
| say that is even welcome: you're aware that its API might chance,
| that its quite new, etc. It gives more confidence than a package
| with version 7.x (at least in informing you that it's prone to
| changes, and allowing you to make an informed choice), IMHO.
| no_wizard wrote:
| Lots of teams, companies, and general best practice all have
| policies and/or guidelines around versioning, and its usually
| something to the effect of _wait till the package is 1.0 to use
| it in production_. I think that 's why there is always a "race"
| to the 1.0
|
| I think we should just push for more date based versioning, for
| instance, CalVer[0]
|
| [0]: https://calver.org/
| earthboundkid wrote:
| All of my Go packages are CalVer v0.year.increment because
| I'm just a lone developer, so nothing I release can be v1. To
| be an actual v1, there needs to be a team of people who are
| committed to keeping a package going indefinitely. I
| understand why people want to use v1, because it sounds cool
| and stable, but realistically if you are just releasing code
| on your own, it is not and cannot be v1.
| zufallsheld wrote:
| Why would a package released as v1 need to be supported
| indefinitely?
| [deleted]
| paskozdilar wrote:
| Semantic versioning serves a purpose - it makes it possible
| to automatically update dependencies to the latest compatible
| version without breaking code.
|
| If you don't need automatic updates, then any kind of
| versioning is fine. Hell, you could get away with just using
| a single incrementing integer. v1, v2, v3, ..., v225883, etc.
| fsociety wrote:
| My biggest pain with Go modules has been the fact that projects
| use 0ver [0] and some are backwards compatible updates and others
| aren't. But it was designed in a way to force everyone to use
| semver. It gets worse if you have a mono-repo because OSS
| projects may depend on a module which depends on a module which
| uses 0ver but minor versions are backwards incompatible. This
| means that dependency conflicts become a nasty situation. Then
| you get into opinion-based world where: - everyone should just
| use semver properly. - everyone shouldn't use v0 for production.
| Or variations on this where some are production-ready and others
| aren't. - everyone should use v0 and only have backwards
| compatible updates. Then fork if you have an backwards
| incompatible update. Feels like everyone loses with how this
| works today. [0] https://0ver.org
| john567 wrote:
| Don't make breaking changes. Make new APIs then transition users.
| Remove old APIs as needed when usage is very low.
|
| Niche people that depend on the old API will stick to an older
| version and be happy with that.
| olliej wrote:
| Sorry, my reading of the article seemed to imply that I should
| have multiple copies of a project in a single repository, one for
| each major version?
|
| That's what branches and tags are for, so what am I missing?
| paskozdilar wrote:
| Let's say you write a Go program using a dependency
| "github.com/foo/bar" v1.0 and post it on the Internet as a
| regular file (or multiple files), without using git. Someone
| else downloads the program and runs the usual Go commands:
| go mod init example.com/program go mod tidy go
| build
|
| The go tool will see the "github.com/foo/bar" path in the
| import statements, download the code from the repository,
| compile and everything will work.
|
| Now, let's say the "github.com/foo/bar" module gets a
| backwards-incompatible change, but does not change the import
| path, and you attempt to do the above process again. This time,
| the go tool will download the incompatible version of
| "github.com/foo/bar" and the build will fail - or even worse,
| succeed but have some logic bugs that will go unnoticed until
| some massive shit happens.
| masklinn wrote:
| So the Go project used a lazy solution to a hard problem
| (packages are git repositories without even a ref as version)
| instead of, say, having an actual versioning scheme,
| therefore you get to implement this by hand using nonsense
| logic.
| paskozdilar wrote:
| Actually, Go used a very elegant solution to a hard problem
| of modularization: directories. A directory == a package.
| Import path specifies a path to the directory that contains
| a package.
|
| A package may, or may not, decide to have a stable API and
| document it. If it does, and it commits to the version 1.0,
| then it basically gives a promise: "This package will not
| change its API in a way that will break correctness of
| currently-correct programs that use it".
|
| Since a package == a directory, if you want to keep package
| compatibility, you must not change the contents of the
| import directory. Therefore, you need to create a new one,
| preferably called v2/, to put the new code in.
| tkiolp4 wrote:
| It's an elegant solution for packages that don't use
| versioning features like git tags. For every other
| package out there that uses git tags, it's just a lazy
| solution: why on earth would I want to specify the
| version in the path? Git tags solves that problem in a
| more elegant way (both from the side of the maintainers
| and users).
| paskozdilar wrote:
| > it's just a lazy solution: why on earth would I want to
| specify the version in the path?
|
| It's not a lazy solution, just opinionated.
|
| Personally, I love the fact that just by seeing the
| import path I know exactly which codebase is used. I
| don't have to open my go.mod, see which version I'm
| using, clone the repository, dig through the history to
| check out a specific tag and see what code is actually
| used in my program... I just open the repo in my browser
| and browse through the directories. There isn't a single
| system on earth that doesn't support directories!
|
| I also love the fact that I don't have to know s**t about
| git to use Go. If Go was to suddenly switch to git tags,
| not only would it break a massive amounts of existing
| code, but would basically force everyone to learn about
| git tags just to be able to see what code are they using,
| which would raise the amount of paperwork I have to fill
| in order to work on the thing I care about. Go is
| fundamentally against needless paperwork.
| chabad360 wrote:
| I'm very confused. Go literally uses refs as versions.
| However to allow for situations where you'll need to update
| a module because of a bug fix or something like that, Go
| allows you to safely automatically update to the latest
| minor version, on the assumption that there are no API
| breaking changes. If there is such a change, Go wants the
| module owner to increment the major version so you don't
| get bugs just from updating.
|
| I will agree that the ergonomics of this method aren't
| perfect by any means. But what it does accomplish, is that
| it forces you to declare your dependency explicitly (which
| seems to be one of Go's underlying principles).
| gowld wrote:
| There is a versioning scheme. It's not golang's fault if a
| publisher doesn't use it.
|
| https://go.dev/doc/modules/version-numbers
| [deleted]
| geodel wrote:
| Kinda useless article. Maybe need to think why they need so many
| major versions so often to break backward compatibility. And if
| one just updates minor versions none of those problems occur.
| donatj wrote:
| I wrote about this a while ago, it was previously discussed here
|
| https://news.ycombinator.com/item?id=24429045
|
| The post itself
|
| https://donatstudios.com/Go-v2-Modules
| iio7 wrote:
| > In fact, we use Go on the front and backend at Qvault, and
| we've found that it's wonderful to have standardized formatting,
| vetting, and testing across the entire Go ecosystem
|
| Well, that doesn't seem to be true as Qvault is clearly a
| Wordpress powered website.
| lowmagnet wrote:
| I worked at a telco with Wordpress powered website. Our control
| panels and backend systems were not Wordpress.
| cryvate1284 wrote:
| Are you sure that's not just the sales website?
|
| Quite common for the sales website to be wordpress and separate
| from the frontend of the product.
___________________________________________________________________
(page generated 2022-03-04 23:00 UTC)