DarkNova6 an hour ago

Step by step, Go is now learning the hard lessons every other language has learned over the last 20 years. The fact that despite their best efforts, their propositions look like everone else is a surprisingly refreshing affirmation of status quo.

  • somekyle2 an hour ago

    I respect "we're going to try not to add features until we have to and have a plan that we like" as an approach to a practical language, vs "we're going to plan to support everything normal modern languages have". It isn't the best approach to language design in theory, but they did try to build a language that isn't impossible to change, and to be fair the mix of language features they chose didn't have any good more successful examples to borrow from, so waiting for enough practical experience to make the relevant trade-offs on practical grounds isn't the bare naivety that some people seem to take it as.

    • DarkNova6 2 minutes ago

      I totally get that. Java is my favorite language for exactly that reason. They are a deliberate "late mover language" and adopt what other languages have proven right.

      But looking at how adamant Go used to be on the whole "No Generics" stance and the path and the troubles they are having... it all seemes so preventable?

    • vlovich123 16 minutes ago

      The problem is that when you don’t have a cohesive picture of how things fit from the outside, it becomes really hard to evolve the language in a way that makes sense and doesn’t break existing code. Data storage and languages share this unique property that the past impacts your decisions and what makes is possible in the future in a way pure logic doesn’t struggle with.

nasretdinov 4 hours ago

Well, better late than never. Stuff like sets or a typed heap is long overdue. Maybe they'll even add iterator API for database/sql results this decade too (something like my pull request for sqlx https://github.com/jmoiron/sqlx/pull/990 but maybe more polished)

  • nasretdinov 4 hours ago

    Also having stuff like a concurrency limiter (instead of doing weird var limiter chan struct{} and using it as `limiter <- struct{}{}` and `defer <-limiter`) as a library function in `sync` package would be great too.

valcron1000 21 minutes ago

22 years late, but better late than never.

jiehong 3 hours ago

Well, finally!

I wish they wouldn’t mix mutation methods in there, but ok.

athorax 4 hours ago

On one hand I'm glad to see this being added, but its becoming obvious building generics into the language as-is just isn't a good fit. Hopefully Go v2 can solve this at a more foundational level while still allowing interop or easy porting form current go code.

  • nasretdinov 4 hours ago

    Why isn't it a good fit? The design prioritises readability of code that uses generics vs writing generic code (which is in line with the overall language philosophy). It also does it in a way that doesn't impact compilation speed or add too much complexity, which is also in line with the language philosophy.

    If you don't like the fact that not all of standard library has been refactored to support the new language features -- I think it'll come over time. Once these features land into the standard library they can't be taken away, so the language authors take their time to make sure it's designed well.

    I don't see anything going obviously wrong here.

    • TheDong 3 minutes ago

      I agree it's not a good fit.

      Go is a language built for people who don't wish to learn any math or CS theory, for people who don't wish to be "computer scientists" but rather "grug-brained programmers".

      The new datatypes will mean having to read things like "sz := sx.Union(sy)", and the union operation between sets is too math-like, and thus makes it less readable.

      "Advanced" data-types, like sets and heaps, only make code more readable to okay programmers, it makes code less readable to the average go programmer. To the average go programmer, a union operation is more readable as a for loop which does not have any math-y sounding name at all.

  • bananamogul 4 hours ago

    I thought the status of Go v2 was that the devs weren't saying it will never happen, but also were not working on it. There was some momentum that seemed to sputter out once generics were added.

    "when should we expect the Go 2 specification that breaks old Go 1 programs?

    The answer is never. Go 2, in the sense of breaking with the past and no longer compiling old programs, is never going to happen. Go 2 in the sense of being the major revision of Go 1 we started toward in 2017 has already happened."[1]

    Granted, this post was more about if there will someday be a Go that will break backward compatibility. But it sort of answers where Go 2 is as a side effect.

    [1] https://golang.google.cn/blog/compat

  • orf 4 hours ago

    Why is it becoming obvious?

troupo 5 hours ago

Go is rediscovering Guy Steele's Growing a Language from first principles, at a much slower pace: https://youtu.be/_ahvzDzKdB0?is=qZdfiT3792XyHxSJ

  • silverwind 5 hours ago

    It's sad that such basic stuff took this long. If we're lucky we might even see a `Map` function in our lifetimes.

    • PrimalPower 4 hours ago

      The beauty of go is YAGNI. Language design makes it much harder for people so do stupid and cute things.

      During my design process if I start realizing that I’m missing maps, More expressive Types, Or more complex polymorphism. I ask myself if I really need those things.

      If I really do. I move off of go.

      That’s the beauty of the language. Go does not need more complicated language features because it’s can handle the majority of trivial software work without unnecessary complexity.

      The language does not need to solve complicated problems.

      • brokencode 3 hours ago

        Ok, and what if you realize you want these things a million lines in? Do you still move off of Go?

        Generic programming isn’t some fancy research language feature like dependent types. It’s just a bare minimum feature in any modern typed language.

        It’s perplexing that after C# and Java both notably shipped without generics initially then added them later that they decided to ship Go without generics.. only to end up adding them later.

        • tialaramex 2 hours ago

          I guess it's possible that C# and Java taught the wrong lesson (you can add this later) and that actually reduced the impetus to ensure Go shipped generics in 1.0

          It is also entirely fair to say there's a lot of complexity here and so there's a risk you exceed your complexity budget which for Go as I understand it was very slim. It is a possible a Go 1.0 with more generics doesn't take off because too many people bounce off the extra complexity and so a decade later it's an obscure thing Google made once that has a few fans but not much adoption.

          Or that extra complexity means Go 1.0 ships five years later, after Rust 1.0 has given people an appetite for better performance and better safety and its sharpest corners have already been knocked off.

          • typical182 2 hours ago

            From what I've seen, I don't think the core Go team was ignoring the lessons of Java or C#.

            Here's a sample quote from Russ Cox from 11 years ago on this site: [1]

            We have spoken to a few true experts in Java generics and each of them has said roughly the same thing: be very careful, it's not as easy as it looks, and you're stuck with all the mistakes you make. As a demonstration, skim through most of http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.ht... and see how long before you start to think "was this really the best way to do this?"

            And of course, they asked other experts for help, including Philip Wadler (of Featherweight Java and Haskell fame): [2] [3]

            We’ve been thinking about generics since work on Go began, and we wrote and rejected our first concrete design in 2010. We wrote and rejected three more designs by the end of 2013. Four abandoned experiments, but not failed experiments, We learned from them, [...]

            Last year [2018] we started exploring and experimenting again, and we presented a new design [...] and we’ve been working with programming language theory experts to understand the design better.

            [1] https://news.ycombinator.com/item?id=9622417

            [2] https://go.dev/blog/experiment

            [3] https://go.dev/blog/generics-next-step#acknowledgements

        • xtracto 2 hours ago

          Maybe at some point it may even get the ternary conditional operator or a proper exception handling syntax.

          Those things that Golang defenders say "dont make sense" until it's implemented, then 'it always made sense" and of course it's a good idea.

        • cyberpunk 2 hours ago

          So your argument is that they should have gotten it exactly right first time and stuck to their guns?

          I mean come on. The Golang team created a useful language people use for building real things — it’s easy to work with especially on large teams, and when the lack of generics turned out to be a pain point in the end (after years of production reality) they understood what the community wanted and actually… added them..

          Now what, it’s not good enough?

          No one forced you to use go.

          No programming language is perfect. I personally find the language has served me well.

          And after being so very pro generics myself, i actually find myself not even really using them that much apart from calling the slices module etc which has them under the hood anyway…

          • brokencode an hour ago

            Nope, I’m saying that the language that was seemingly designed with either an ignorance of or disdain for the hard-won lessons from decades of prior programming languages.

            There was even this condescending attitude that Google engineers couldn’t understand fancy languages anyway, so they had to dumb Go down.

            My criticism really isn’t even about Go itself. Yeah it’s improving, which is great.

            My criticism is about this anti-intellectual attitude that has permeated the entire Go community since its inception. It’s like hearing that college is a waste of time from people who never graduated high school.

            • inigyou 44 minutes ago

              my criticism is that if we make every language identical, we might as well only have one language. (C++, obviously)

              There is room for a language without generics. There was a language without generics. Now there is not.

              • brokencode 20 minutes ago

                Well here’s the thing on generics. Go always had generics since the very beginning. It’s just that only certain built-in types had them.

                Slices, maps, and channels all were generic from day one. Same with functions like append, copy, etc.

                Your criticism makes no sense unless you think Go shouldn’t have had generics from the start, which it did.

        • improgrammer007 2 hours ago

          This. One should never pick a language that regresses in terms of features from the get go.

    • inigyou an hour ago

      Go's whole philosophy was to keep the language simple. It's a shame they're abandoning that now and becoming the next C++/Zig/Rust/Java

    • bborud 2 hours ago

      This is also why people eventually leave languages. Satisfy everyone’s wishes for long enough and you get lots of different styles of doing things and … «wow look at that much simpler language over there; let’s try that instead»

    • wannabe44 4 hours ago

      Map function leads to poor code in Go. Function literals are verbose and inlining is far less agressive. It simply isn't the way of the language. Even python shuns map and filter in favor of comprehensions. A for loop is more readable than the lambda soup.

      • ninkendo 3 hours ago

        IMO it depends on the language… to me, map/collect/etc are useful in languages that have the concept of immutable data, because you can initialize an array with a single call chain, and be sure that nothing after that can modify it.

        What I’ve seen in the “for loop” approach that I can’t stand, are things like (pseudo code)

          var a = []
          for x in coll1 {
            a.push(foo(x))
          }
        
          do_stuff_with(a)
        
          // … further down the function
        
          for y in coll2 {
            a.push(bar(y))
          }
        
          do_other_stuff_with(a)
        
        Reading code like that, is the first call to do_stuff_with(a) a bug, because it’s not fully built from both coll1 and coll2 yet? Or is the second call to do_other_stuff_with(a) a bug because a now contains more stuff than the developer probably thought? Can I safely move both loops next to each other, or does that break something subtle? If I need to pass a to a new function, where can I safely do this? Before or after I add from coll2? (In my actual times seeing this, a is really a map of cached key/values or something, and it’s kinda ok that the contents were different each time it was used, but subtle bugs emerged…)

        IMO the sane way to do it is to just not incrementally mutate things like that, and stick with giving things a single place where they’re defined and initialized. Go doesn’t really help you here because there’s no such thing as immutable data. So just adding Map/collect or whatever doesn’t really buy you much.

        • tialaramex 2 hours ago

          Often the mutation might have performance benefits.

          Of course if you're Rust the stdlib and compiler might conspire to optimise an operation you wrote which reads as non-mutating into an actual mutation which was faster.

          This is another benefit of the "destructive move". If I consume X and spit out Y, the X is gone, so it's OK if secretly I just mutate X and tell you that's Y now.

      • troupo 3 hours ago

        map functions are very useful for iterating over collections. Most functions iterating over collections are useful, because a lot of the data you're commonly dealing with is collections. And most collections are generic.

        > Function literals are verbose and inlining is far less agressive.

        > Even python shuns map and filter in favor of comprehensions.

        That's the problem of the language design. And Python isn't the best language to turn to for language design

        > A for loop is more readable than the lambda soup.

        A for loop shoving modified items into a temp variable with append() that is then returned is less readable than a map function transforming data. Too bad Go decided to turn lambdas into unreadable soup.

  • pstuart 5 hours ago

    Sounds like a win to me. I'd assume that many PL decisions come with with costs of either implementation or readability, and Go's conservative evolution takes that into account. Disclaimer: not a PL designer, just a codemonkey.

    It's not a perfect language, and the process has not been without its pain points, but work like this makes the language more powerful and I feel like I get my money's worth when I use it.

    Yes, I'm a Go fanboy but I'm not interested in language wars (e.g., yes Rust is more performant and correct but sometimes "good enough" is good enough).

    • cyphar 4 hours ago

      On the other hand, design decisions made under one set of constraints can become problematic when you add new features that don't play as well with earlier design decisions.

      For a concrete example, the fact you cannot define custom methods for external types in Go (a pre-1.0 design decision) means that you cannot write proper compile-time generic code to deal with some generic wrapping type (dumb example -- getting a sum of the perimeters of a generic set of shapes in an externally-defined collection type) -- you are forced to work around it with runtime type-switching. There are all sorts of arguments you can make about simplicity but this is an objective shortcoming of Go that is directly caused by generics being added to Go long post 1.0.

      My take on this is that despite selfishly wanting more from Go for many years myself, adding more stuff to Go at this late stage is just slowly chipping away at Go's uniqueness with features that make a large number of people using them unhappy. (For example, while they make some APIs nicer, iterators turn a basic logic bug that is impossible with for loops -- forgetting to stop iterating when the loop has a "break" -- into a runtime panic. And they really suck to compose.)

      • aatd86 4 hours ago

        __For a concrete example, the fact you cannot define custom methods for external types in Go (a pre-1.0 design decision) means that you cannot write proper compile-time generic code to deal with some generic wrapping type (dumb example -- getting a sum of the perimeters of a generic set of shapes in an externally-defined collection type) -- you are forced to work around it with runtime type-switching. There are all sorts of arguments you can make about simplicity but this is an objective shortcoming of Go that is directly caused by generics being added to Go long post 1.0.__

        I'm a bit intrigued by this: how would that work with compatibility between libraries, separate compilation and what not? My first instinct is that it would not be a good idea but I might be missing something..?

      • troupo 3 hours ago

        > (dumb example -- getting a sum of the perimeters of a generic set of shapes in an externally-defined collection type)

        There's a much more common example: dealing with external APIs that return JSON. Their response is trivially wrapped in Req<T>. Pre-generics Go would force you to write tedious duplicated boilerplate code for each request type, or just "cast to void*" with interface{} and hope for the best.

        > adding more stuff to Go at this late stage is just slowly chipping away at Go's uniqueness

        Uniqueness should not be the goal of a language.

      • pstuart 4 hours ago

        Fair enough. Primeagen did a video recently renouncing his love of Go over the concerns you've raised.

        That said, I'm assuming much of this "wobbly" functionality will live in libraries and will not be common in day to day coding (much as I've seen with generics so far). It's all optional after all.

        I use Go because it's simple, capable, and been my prime language for over a decade and that skill enables me to be valuable enough for a decently paying job.

        If I were younger with more energy and time on my hands I'd likely be a rustacean but I think I can ride out my career on this. YMMV.

        • cyphar 4 hours ago

          I've maintained one of the major container runtimes (which is written in Go) for over a decade as well, I think I have a less rosy view of Go than you but I still think it's a nice language all things considered and still use it for some projects.

          • pstuart 4 hours ago

            My goal is to be pragmatic about the issue (and everything else).

            When I started with it I saw it as the love-child of C and python. Then saw it as a successor of Java.

            I recognize that Rust will win this contest (although my understanding is that async still has sharp edges to round down). I'm old and tired and have lost the energy and focus for exploring new languages and believe that despite its shortcomings it will continue to have enough value to be useful.

            Good enough will do for me. I tip my hat to the all the other PL contenders and wish them all well (except Java -- PTSD from that destroyed any love I had for the language).

            • wbl 37 minutes ago

              Rust will not "win" when it targets a much different niche, any more than C won against Java or Scheme.

    • tikhonj 4 hours ago

      "Everything is a trade-off" assumes you're on the Pareto frontier.

      Go is... very much not on the Pareto frontier of programming language design.

      • whateveracct 3 hours ago

        > "Everything is a trade-off" assumes you're on the Pareto frontier.

        100%. it pisses me off so much that i have to hear this idea thrown around constantly.

      • fragmede 3 hours ago

        Somewhat. The trade off is it can be made more complex at the cost of its simplicity. You can argue that some of those tradeoffs don't in fact have to be made because it's not on the Pareto frontier, eg generics, but we'd have to have a specific discussion about specific language features instead of vague generic discission about the language.

      • pstuart 4 hours ago

        I find language wars tiresome at this point. There was no claim that it was a frontier language, or even that it was a great language. My point was that the Go authors do try to consider the impact of enhancements to the language, which I think is appreciated by many that use it.

improgrammer007 3 hours ago

First they said they won't add generics. They violently defended that decision. Developers bent over backwards to make it work without generics. Some even wrote long blog posts defending Rob Pike's decision. Some wrote posts arguing against it. Now the Golang team adds them. Why waste so much developer time? It's not a few months. It's several years. This industry is seriously a clown show tbh.

  • pphysch 3 hours ago

    At this point, the "damage" has been done and even skeptics of generics/iterators should applaud this proposal since it means burying some of that added complexity behind straightforward stdlib interfaces.

    Unless they are just here to complain, of course.

  • saturn_vk 3 hours ago

    Violently?

    • rapnie 3 hours ago

      Too much. More like vehemently. Perhaps parent meant to say that.

  • pstuart 3 hours ago

    Core members of the language team (Robert Griesemer and Ian Lance Taylor) argued for generics from the very beginning. The team resisted because they didn't know how to do it without sacrificing speed of compilation.

    Rob Pike did a lot of defensive work to deflect it but I'll quote him here on the issue when he said "There are no plans for generics. I said we're going to leave the language; we're done":

    "I meant there are no plans for generics. That's not the same as saying we plan not to do generics. It just means we don't have a plan."

    You take it as a conspiracy against developers when it's really a small team trying to find their way the best they can.

    • improgrammer007 3 hours ago

      It's an utter waste of time for developers, business, everyone. Millions of lines of Go code have been written without generics. Libraries have been written. Support, maintenance, cost, etc. This is why one shouldn't pick languages that regress in features from the get go. Now developers will waste time migrating the code to stdlib. This is not solving problems. This is doing tech for the sake of doing tech. Wasting everyone's time. Remember that code is not the deliverable.

      • wbl 36 minutes ago

        Nothing was broken in the change: there is no need to migrate.

      • jppittma an hour ago

        Claude will migrate your whole repo in an hour.

      • pstuart 2 hours ago

        I'm confused by what language regression you are referring to.

        > Now developers will waste time migrating the code to stdlib

        Why? If it works now it works. Refactoring tools exist, and LLMs make this trivial.

        You just seem to hate the language and everything about it, and that's your right but I think your arguments are specious and ignore that most language that go mainstream evolve and that comes with tradeoffs (python2 -> python3, rust in general, etc).

        And as far as deliverables go, the code is absolutely foundational to that and Go was made to be maintainable by codemonkeys such as myself.

        Anyway, the language and the changes noted in the OP apparently aren't for you and that's ok -- there's plenty of languages out there for everyone's taste.

  • amazingamazing 3 hours ago

    What’s wrong with meeting demand?

    • improgrammer007 3 hours ago

      Nothing is wrong. What was wrong before when they vehemently argued against adding it? Is that design principle/core value lost now?

      • ninkendo 2 hours ago

        Reminds me of when Apple finally moved the iPhone to USB-C… they defended lightning for the longest time, but then when when they finally did the switch, all I could think was “the last N years [0] of lightning accessories I’ve bought are now ewaste”… once it became clear USB-C was going to be the future, every year they weren’t using it was another year of future ewaste building up.

        Every year go didn’t have generics was another year of workarounds and tech debt building up that would have otherwise been able to be written the right way from the start. Unlike ewaste though, it’s probably impossible to quantify.

        [0] I’d probably peg N as the years between when they gave MacBooks USB-C ports for charging, up until the iPhone got them. It’s clear Apple knew they were gonna need to move to it eventually… every year in that period represents a year of lightning cables people bought that could have been still-useful USB-C cables today.

      • amazingamazing an hour ago

        It is not a monolith, maintainers change? Why does it matter so much to you anyway? You can choose not to use generics

znpy 4 hours ago

Looking forward to see G2EE being released as a specification /s

  • throw_m239339 3 hours ago

    Nothing wrong with J2EE back then if you were building a certain kind of entreprise application. EJBeans actually took care about a lot of business complexity for a n-tier application, it's just that the whole XML crap was absolutely egregious.

    Go can barely parse an XML document natively so don't worry about G2EE I'd say...

    I'm more worried about what have become of professional Javascript serverside these days, it's just nuts how people have managed to make it as complex as J2EE... Nextjs, Typescript,JSX, React, compilers, transpilers, ... and none of that stuff solves enterprise business logic...

    • znpy an hour ago

      Absolutely, i was just being ironic :)

shevy-java 3 hours ago

Golang's biggest problem is a certain company.

akiarie 3 hours ago

Honestly the more I see this the less I like Golang. Generics was the worst thing ever added to the language. We're making it easier for library builders and harder for ordinary code to be written.

  • jerf 13 minutes ago

    Do you use Go? Because it sounds like no. In the last four years I've encountered I think two uses of generics in the wild in a 3rd party library. Both quite sensible.

    Anyone moaning about how it's ruined Go is either not using Go, or simply impossible to please.

    If you hate Go... and hey, you do you, I've got my own list of languages I don't like... find a better complaint because this one is simply nonsensical. "It doesn't let me map/filter/reduce" or "it doesn't fix lock problems" or other similar complaints have some grounding in reality, but this one is just absurd. Generics aren't used enough to be "the worst thing ever". Fears about how Go would instantly turn into a language full of generics that take generic arguments that take generic arguments have proved to be wrong.

  • woodruffw 3 hours ago

    Is there a categorical division between “library builders” and “ordinary code”? That’s not one I’ve heard before.

    (I’m aware of the difference between application and library code, but every large codebase I’ve ever worked in is a mixture of both.)

  • troupo 3 hours ago

    Here's a quick example of ordinary code that is much easier to write with generics: https://news.ycombinator.com/item?id=49128954

    Working on any collection is easier with generics. Working with anything that accesses data in uniform way (APIs, SQL etc.) is easier with generics.

  • pphysch 3 hours ago

    This proposal is literally about making it easier for ordinary code to be written without defining new generic types or iterators.