Watching Go's development is like reliving the development of Java (which also didn't have generics at first), but over decades instead of years. Cannot wait for Go to implement an error handling system in the 2030s.
Its very funny watching certain segments of the programming industry rediscovering incredibly basic programming principles, after railing against them for so long. The AI people are starting to try and create formal specs to force the AI to generate an exact output, which is absolutely hilarious to me
Dynamically typed/untyped languages finding that strict and visible typing is actually good is another
They didn't say they never wanted to do generics, but that they did want to take their time and do them right.
Debatable how much they have been "right", although this gets them somewhat closer. And I think they have not been "wrong" in the ways they wanted to avoid (they referenced some issues with Java generics as prior art, although I forget the details).
> “What do you think? There was a man who had two sons. He went to the first and said, ‘Son, go and work today in the vineyard.’ “ ‘I will not,’ he answered, but later he changed his mind and went. “Then the father went to the other son and said the same thing. He answered, ‘I will, sir,’ but he did not go. “Which of the two did what his father wanted?” “The first,” they answered. Jesus said to them, “Truly I tell you, the tax collectors and the prostitutes and the Go language maintainers are entering the kingdom of God ahead of you.
Whether they made a good decision or not, or changed their mind or not, is beside the point (I think they did, and they did!). I was merely replying to the claim that
> They didn't say they never wanted to do generics, but that they did want to take their time and do them right.
Is anyone actually mad about this, or do people just bring it up to stir the pot? Who cares what the FAQ says? They've worked out a way to add it easily in a backwards compatible way that can solve some problems. They had not identified this solution at the time they wrote the FAQ, and Go has been perfectly usable without this feature for 16 years.
What’s the correction? The two claims are not in conflict. Saying “we don’t expect to ever add X” is not equivalent to “we never wanted to add X.” It simply means that they didn’t think it would happen, which can coexist with an underlying willingness to consider it if a suitable approach appeared.
We care that time and time again, when anyone ever brings up a criticism of the language, they’re told that everything is just fine and it’s not a problem and we just don’t get the Go Philosophy. There’s not a problem, stop trying to make Go like every other language, and changing things would make the language more complicated and worse.
Then when the language is inevitably changed for the better, resolving the complaint, suddenly it was always going to happen and it was just a matter of getting the details right.
Every other language community I can think of is more than willing to acknowledge the shortcomings of their language. “Yeah, this kind of sucks in principle but it’s not something that gets in the way in practice” is a fine perspective. So is “this was a tradeoff; we went in this direction and these are the resulting downsides”. But the golang community practically trips over themselves to constantly argue that obvious shortcomings in the language are actually a good thing and we just don’t get it.
Nobody is saying the language shouldn’t improve. We’ve all been begging the language to improve. But we’re also tired of the constant, obvious, and shameless gaslighting from the community whenever things do get better. You aren’t going to like the comparison, but it’s extremely Trumpian.
Yeah, I worked with a guy in the late 2010s - one of the most painful people I've ever worked with - who would tell anyone that would listen that Go (as it was in 2018) was the perfect programming language - it had all the features you'd ever need - no more, no less. It doesn't need generics, the package management story is fine etc. Thankfully he's been out of my life for a long time now but I believe he's still writing Go, and I bet that he's telling anyone that will listen that Go (as it is in 2026) is the perfect programming language and that its implementation of generics was necessary and perfect etc.
He wasn't the only one but he certainly took it to the extreme.
This is an outlier. The Go team and community never endorsed that. In fact, their position has always been the opposite. To give just one example, see [1].
But they haven’t added generic methods, really. This change just lets you use method syntax in cases where you could have used a function. It’s a pretty conservative change that I think a lot of people here are misunderstanding. Actual generic methods wouldn’t really make sense (for the same reason that you have similar restrictions on dynamic trait implementations in Rust).
There's a critical difference between "we don't think we will add it" (what you quoted) and "we won't add it because we think you don't need it" (what OP claims)
Depends you who "they" is. If you mean the go development team, then yes, they said they wanted to "take their time and do them right"¹. But there are many "gophers" who did say that there was no need for generics, and that it shouldn't be added to the language.
¹ I would argue that it is really, really hard to add generics to a language after it has already matured, and still "do it right" than to add it in the beginning. At least if you care about backwards compatibility. Backwards compatibility adds a lot of constraints to your generics system that will almost certainly lead to a sub-optimal design. And you will be stuck with a standard library, and a lot of existing ecosystem code that would benefit from generics, but don't because generics didn't exist when they were written. This is a lesson I wish go had learned from Java's generics.
I agree that they were clearly not in a hurry. I disagree that they are doing everything right. I am interested to see how they will fix the 'million dollars mistake'.
Maybe, but personally I've become quite tired of programming languages "organically grown" as opposed to properly designed the first time. After a good decade of C then C++, I found ANSI CL (despite being a massive compromise and unfinished) much more coherent and complete than both.
I know Go is justly criticized for many of its design decisions, but it still feels well-designed and "small" to me in day to day usage when many other languages don't.
Eh, the thing with generics coming late is pretty much what I meant by "organically grown".
My best litmus test these days is support for multidimensional arrays because it's always needed at some point in general purpose languages. CL and Ada had it right from the start while C++ needed C++23/26 to get std::mdspan and we still need to wrap it to pass the underlying/owned memory pool around (https://rosettacode.org/wiki/Multi-dimensional_array for more).
An array of arrays is an extremely inefficient and error-prone way to represent multidimensional arrays.
If I want a 1000x1000 array, representing it physically as a single 1000000-element array requires one allocation, and processing it element-by-element (assuming it's stored in the same order we're iterating over it) is sequential in memory and therefore very efficient.
Representing it as 1000 separate 1000-element arrays requires 1000 allocations, and pointer-chasing every time we move from one row to the next.
I liked Objective-C (except the C parts). Such a breath of fresh air coming from C++ which was grown like a cancer with tons of features and you felt trapped by every one of them.
Objective-C in contrast was a very few additions thoughtfully added that composed cleanly and freed the programmer to actually get things done.
Scheme is (or at least was) coherent. You don't need to look any further than set/setf/setq to see that Common Lisp is "organically grown" from the fertilizer of a committee. CL does its best to make every other lisp more attractive.
I mean, good choice, but you see the point, right?
As much as ANSI CL has it's flaws, it has a standard, as much of a mixed bag it might be. Scheme is just a general potpourri of "we kinda have a guideline, but do whatever".
I would very much prefer scheme if the different implementations had a working standard. But I can't take my Chez-scheme code and throw it into Guile-scheme.
But pretty good chance I can take my ECL code and throw it into SBCL or LispWorks.
Scheme has a coherent and minimalist design, but its ecosystem and abstraction facilities feel too sparse for large applications.
When I started building a Lisp-based machine learning framework, Guile seemed like the right choice because it provides GOOPS and generic functions, yet I still ended up with a lot of boilerplate to compensate for the lack of a strong type system.
Scheme feels to me like C is to C++: not ergonomic for large-scale application development. Go is one of those languages that has both minimalism and productivity.
It isn't realistic to expect a design to be "proper in first place" because requirements change; my opinion is indeed the opposite - I find it natural for programming languages to have a (sort of) lifespan, and for new ones to (sort of) take their place.
Sure but literally everyone and their mom said these features were needed and then Go team said "nuh uh!!!" But, as it turns out, they are needed because they solve real problems, and are not just fake complexity like some people strawman.
Hopefully next they can add some error handling syntax and controls.
I think Elixir is a good candidate here. It's small, coherent, and composes well, and (at least to my understanding) the authors consider the language finished, with no new major features planned.
That’s whataboutism - no language is perfect, but given when go released it’s fair to hold them to a higher standard than languages what were designed 25 years earlier.
As an aside - D, Zig, Rust, even typescript got most of the lessons learned from C right
And besides Rust's high count of RFCs, there are things like async (I'm not complaining about it, but its an obvious large-scale "change"), module system changes, etc.
(To be clear, I like both languages a lot. But I wouldn't call them slow moving or right from the start.)
D literally can't even maintain backwards compatibility between minor version updates not to mention a big part of the D community left when D reinvented itself with D2. Among languages it's probably the one that is constantly in a state of flux.
ANSI CL is such a breath of fresh air nowadays. Does what you need, doesn't get in your way, comes with batteries included. And conditions are just god-tier.
And to bring it full-circle, this is the exact same thing I run into with Go. When I mention how nice it is that Lang X has feature Y, someone is quick to point out that either, "You can BUILD that in Go" or, "You don't really need feature Y". We've proven that we don't really NEED compilers either... but I would hate to have to do my job without them.
I am actually working on my own language, and getting something better than Go is actually not that difficult!
The hard part about making a language is creating the stdlib and tooling and support for the language, but actually creating a language itself that has more features and better features than go can be done by a single person in a few months or a year probably, depending on how much experience they have.
Generics specifically are a great example here. A single person can implement a language with go-level generics fairly easily.
Something can be highly succesful in spite of having glaring design flaws. Nobody is claiming go isn't wildly succesful, but it's _in spite_ of these issues. It was clear over a decade ago that iota, gopath, and lack of generics were massive kneecaps to the language; go changing it's mind on those things isn't progress it's just getting the fundamentals wrong.
A good example of where they're kind of stuck is date formatting - it's stupid, unclear, and likely a mistake, but it's not a fundamental flaw; it's just a quirk.
Why is iota a massive kneecap to the language? It is semantically identical to enum in C and Typescript.
The trouble is that Rust is older than Go and it was already confusing people into thinking enums and sum types are the same thing, so by using slightly different syntax, iota, Go avoided the whole confusion of users thinking that enums would behave like sum types instead of actual enums.
Is your attempt at making a point that not having sum types is the massive flaw? Sum types are a useful construct, to be sure, but there are plenty of good languages without them. That's more on the design quirk end, realistically.
> Why is iota a massive kneecap to the language? It is semantically identical to enum in C and Typescript.
iota is a massive kneecap _because_ it's semantically identical to enum in C and Typescript.
> Is your argument actually that not having sum types is the massive flaw? Sum types are a useful construct, to be sure, but there are plenty of good languages without them. That's more on the design quirk end, realistically.
In a dream world sure we'd have full blown sum types (and that would give a result type which would also solve a lot of the nil-interface-combined-with-error-handling issues that I've ran into when working with go), but I can forgive that. The problem is this - https://www.zarl.dev/posts/enums
I can't speak about Dart, but Carbon had just barely started development when it was first announced 4 years ago, and is currently presented as an experimental language that is not yet ready for use [0].
Dart was relegated to effectively being Flutter. It was originally intended to supersede JavaScript but no other engine would commit to that. It failed at its initial goal and hasn’t really found a footing outside of Flutter.
Carbon is by its own admittance not ready to use and I think mostly relegated to solving Google’s problems with C++ right now.
Both of them didn’t ship with a standard library as robust as Go’s.
One thing that made Go popular out of the gate is it is extremely good fast to build out robust HTTP services and infrastructure.
This is a very common use case and they tailored Go to be a great fit for it. You can build your entire backend without a single third party module if desired using Go’s standard library and it isn’t terribly complicated to do so.
By that logic Windows would be the best operating system ever and perfect in every way, and anyone who disagrees must be wrong about how an OS should be.
An engineer, of course, understands that there is no such thing as "wrong", only different tradeoffs, but with the rise of "vibe coding" you don't need to be an engineer to play in the world of programming anymore.
I don't think anyone admitted any wrong or had any big change in philosophy. It's always a good thing to learn something along the way. But the current message seems to be that this was the plan all along, and it just took some time to design properly.
Of course adding generics is not something that every language needs to do. Scripting languages like Ruby don't really need this style of generics. It doesn't fit the design of the language, and it's not even clear what that would look like in Ruby.
But static typing with generics does solve a recurring problem, and we've seen some real convergence towards type hints and type systems even in staunchly dynamic scripting languages. Modern Javascript is now mostly Typescript, and they've successfully retrofitted a very advanced type system in the last place I would have expected 20 years ago.
Type hinting seems like the worst of both. You pay the cost on refactor to go change them all, where dynamic typing or static type inference avoid that. You also don't have any of the benefits of static or dynamic typing. My strong preference is static typing with good inference and an ide that shows the inferred types everywhere when asked. Dynamic typing can make some tasks dramatically easier, I'm just not capable of using them without making hideous mistakes.
It’s still annoying ~20 years after Java did the same mistake of not including generics, which was already clear to many people with C++ experience back then.
...and Java didn't even have basic enums or sum types from the beginning. But it had null.
They added enums, they added sealed classes. They're trying to get rid of null (apparently it's really hard). The problem is that in 2012, when go 1.0 was released, this should have been obvious to everyone.
Here's a famous discussion from 2009, three years before the 1.0 release (tldr: facepalm)
I remember back in 1995 thinking that it was stupid for Java not to have generics, so instead you had to always cast Vector/Hashtable elements from Object, or implement your own type-specific container classes for every element type (and there wasn’t even a preprocessor to facilitate the latter).
Sum types I didn’t really miss, because you can implement a type-safe equivalent using the Visitor pattern, and retain an interface-implementation separation that native sum types typically don’t provide.
That is an interesting read, seems some were having a hard time grasping the benefit of having compiler checks for potential null dereferences. Having worked with null safety in TypeScript and Kotlin the extra bit of strictness is nice.
The biggest design issue with adding value types and non nullable to Java, is that the number one design requirement of any solution is not to break Maven Central.
Every compiled JAR out there has to keep working as always on a JVM with updated semantics, and worse code has to be compatible, when passing class instances around between old and new code.
Then there are the guest languages on the JVM as well.
Exactly. We heard for years they wouldn't do generics it until they could do it right, and that was perfectly fine with me. Who wouldn't want a well thought out implementation? Then they released generics and it was like, "this is what you thought was the right way to do it?!"
What’s the approach they should have used instead and how would it be better? Especially in terms of keeping fast compile times and overall performance.
Of course, if you go back and watch the original Go announcement it said that it would need generics once they figured out how to do it. And when the first version of generics landed it was said that generic methods would be added later, once they figured out how to do it. So that isn't applicable here. The need was always recognized.
If Go had just taken an off-the-shelf implementation of generics in 2009 then they could have spent the last 16 years deliberating over something useful, rather than attempting to reinvent programming language theory.
The impression I have always gotten from Go's designers is that they are rather arrogant and averse to the idea of using other people's work. They want to develop everything from first principles, but by so doing end up with poor reinventions of well-studied concepts.
> and averse to the idea of using other people's work.
They did use someone else's work, though. If you recall, Philip Wadler (of Haskell fame) designed Go's generics.
> but by so doing end up with poor reinventions of well-studied concepts.
Which is funny as there is probably nobody on earth that would be more capable than Wadler to get the job done. His pedigree in that area of work is pretty astounding. If he couldn't do more than create a poor reinvention, what hope did the laymen working on the Go core team have?
Answer: They had no hope. It's not like they weren't trying. Ian Lance Taylor, for instance, is well known for beginning work on generics in Go before it was even first released to the public. He, among others, quite simply, were unable to figure it out.
Everything looks easy and straightforward when observed comfortably from an armchair, I suppose.
Yes, the same guy that supported the effort to add generics to Java, a decade beforee Go came to be, talk about not getting language design history.
Stop excusing them, they were the first to acknolowdge being wrong in first place,
"They are likely the two most difficult parts of any design for parametric polymorphism. In retrospect, we were biased too much by experience with C++ without concepts and Java generics. We would have been well-served to spend more time with CLU and C++ concepts earlier."
What is there to excuse? Your quote confirms that they simply don't know what they're doing as was already established. Not that anyone should expect them to. They're just regular average humans, same as every other random Joe you encounter while walking down the street, who all equally have their own failings and shortcomings. Why HN is constantly trying to put these particular people on a pedestal, I'll never know. Jealously that regular bumbling idiots just like them accidentally stumbled into creating something popular (for some definition of popular), perhaps?
Where did "they" say "we" didn't need generics? That sounds like a bad faith / misinterpretation / straw man; as someone else pointed out, they postponed generics until they figured out the use cases and whatnot.
Remember that the generics implementations in other languages (like Java) take up half the spec + implementation - that's not something that Go wanted.
You keep posting that. Do you understand the difference between that and "we anticipate that Go will never add generic methods"? What they actually said shows epistemic humility and recognizes that they might change their mind.
Hi! I'm a human being that is trying to understand the world and make friends along the way. I see you are too! Pleased to meet you.
You asked the question
> Where did "they" say "we" didn't need generics?
And I (re)posted a quote from them, which sounds to me like, at the time, they believed that "we" Go users didn't need generics.
They may have changed their mind, which is totally fine! But I do think it sounds like the person you were replying to wasn't commenting in bad faith or misunderstanding or fighting a straw man as you posted. Seems like a reasonable interpretation of what the Go devs had said at one point. To each his own though!
Hi! If you want people to think you are a human, you should not mistake one of them for an entirely different one, and you should not refer to yourself in the third person.
The OP didn't mention generics or generic methods :) They referred to something that was added, after the Go team didn't anticipate adding it. Sounds like a fair point to me!
I frankly don't buy into this trope that a lack of monetary cost should shield something from criticism. Anything created by humans for other humans, especially tools meant for getting work done, should certainly be open to evaluation/judgement/critcism, regardless of whether the creator chooses to charge for it.
And it's not like Golang is some freshman student's hobby project; it was created by one of the world's largest tech companies, by people with a strong pedigree in programming language design.