What kind of new libraries are we going to get with this change? Seems like we'll see a proliferation of new data structure libs now that they can be constructed without interface{}. What else?
Libraries that assemble channel structures, and libraries that may not provide that functionality but depend on it internally, i.e., libraries that can set up entire structures of goroutines that use channels under the hood. (Probably another burst of "worker pool" libraries will pop up before once again the community points out that native Go essentially provides worker pools with a natural use of existing constructions already.)
While this is a subset of "new data structures", I'm really looking forward to generic immutable structures that can be read by many goroutines but have some coherent update story. I've got several places in my code where I have a structure I want to update infrequently and have read access in a lot of places, where I'm reading it enough that a traditional read/write lock is a real problem. I've got some stuff hacked together but what I have can't be shared as a library, and I shouldn't anyhow, because a real library ought to be stronger and better.
(I recognize that Go doesn't have immutable data types, but I was programming in Python for many years before Go and have made my peace with "Just don't do that.")
Libraries that operate on maps and slices in a type-agnostic manner.
Probably some numeric libraries with nicer types than you can get now, though I still think Go will be a bad choice for highly numeric code even post-generics.
Several hundred map/filter/reduce libraries that nobody will use for very long.
Data structures are the one I'm really looking forward to, though. Network servers, nominally Go's wheelhouse, is one of those places that we tend to like some obscure data structure choices because of the performance needs. It has been a frustrating hole in the language for a while.
Back in the day, if you mentioned generics on any Go post on HN, you would be downvoted to the hell, interesting how everything comes full circle (unfortunately a bit late).
Same with the hand washing/wearing masks inversion regarding COVID19 - people made fun of you two months back for preaching the obvious, and now nobody will even go as far as admit they were wrong, let alone apologise. Human nature. ️
IIRC, that's because it got mentioned on EVERY Go post. People got tired of "Go should have generics!" and the ensuing arguments dominating every discussion about Go.
Comments like yours are exactly the reason, the mentioning of generics lead to quick downvotes. Not aknowledging the reasons for not having generics right off the start, which have been clearly communicated by the Go maintainers. Comments, which don't add any substance to the discussion (usually they were even made out of context) and are pure nagging.
Go is on its way, like everything, through the Hype Cycle. It started at the Peak of Inflated Expectations ("Java will disappear overnight, and I sure hate Oracle and that one Java program I heard about 15 years ago"), and at that stage, any article that mentioned Go would get upvoted. Then came the Trough of Disillusionment. There were probably enough HN readers that had used it to realize that it wasn't the solution to every problem -- bad Go written by bad programmers was bad! I was promised that was impossible! It became the subject of flamewars both from bad experience and to push back against the visibility people didn't think it deserved. (Lots of reasons for this -- they wanted to write something in Go and nobody let them, Go came from Google which HN hates, etc.) The pushback here that really got traction was "Large company that I would normally hate because they sell ads has rewritten some small Go microservice in a new cool programming language." HN was willing to ignore its hatred for large companies, ads, and microservices as long as the article was shitting on Go. You gotta null out the Peak of Inflated Expectations somehow. Now we have entered the Slope of Enlightenment. Go has most of what it needs to be successful, and is objectively successful. So now it can be tweaked and refined -- time spent in the trenches making TLS or HTTP/2 or GC better has mostly made those things better, and it's on to the next things -- generics being the big one.
You should watch the Hype Cycle very carefully with Rust. Rust is no doubt on its way to a Plateau of Productivity, but right now we're at the point where "My company only uses Rust!" or "I rewrote my foobarlang app in Rust!" will get you to the first page... but "Wow, my CI system spent 387 CPU days building my Hello World app last week!" is also starting to show up (on its way to the Trough of Disillusionment).
I hate when things fall into rigid categories because it seems overly simplistic, but the Hype Cycle is spot on. Look for it and you'll see it everywhere.
People were pretty excited back in the day. We may look back on this excitement and think it's unrealistic, and indeed it is. That is the Hype Cycle at work. People can't get enough of the shiny new thing, and will inflate things to make it look even better than it is. You have to watch out for the effect, as it's very common. The inflated expectations is what causes the transition to the Trough of Disillusionment as people begin to realize that what they were promised is an impossibility. In the case of Go, the lack of generics was a good sticking point. Here an article has promised me that Java is dead. But Java has generics. I guess I was lied to! The result was many breathless battles over whether or not generics were really necessary.
Again, you have to understand that HN's biases play into this effect. There are many people here that want to be at the forefront of the field, but are outraged when they have to show up at an interview and code up a data structure on the whiteboard. If generics were in Go, then someone else would have already written the data structures, and they could continue to believe that the practicing programmer has no need to ever look at a computer science textbook. But the reality is, when you use Go, sometimes you have to show up and write an algorithm or a data structure. (The most common one I've written is an ordered set; a slice with the keys, and the keys and values in a map.) So you can see why emotions are going to run high. Two ideals are in direct conflict -- and generics are going to solve the emotional problems. Thus, much is said and argued on these topics.
I have to say, I sleep way better at night knowing that the Go team is around to deal with all this stuff. There is a lot of arguing and strong emotions, and they sort through it all and continually produce something that seems sane. Because they do such a good job, I don't have to feed the hype cycle, I can sit here and enjoy the view from the Plateau of Productivity.
Hype cycles are real, but Go wasn't really involved in one. Go generally lives up to its promises; with a few exceptions, Go's critics mostly take issue with Go for eliding features they believe are necessary for software development--their criticisms are framed as "Go lacks features I like so it can't be good". In particular, they're often (but not always) inexperienced with the language and haven't actually tested Go's specific feature set with respect to whether or not it improves their ability to develop software (i.e., they have faith in their favorite features, but aren't willing to test that faith by trying Go in earnest). But there's no material "trough of disappointment"--people who tried Go mostly like it and find that it lived up to its promises and most of the critics are simply disingenuous and defensive (this isn't a convenient writing off of critics, it's evidenced by the substance of their criticism--not that this will spare me any downvotes).
I am not sure what to make of search trends. I compared Go with Objective C and Swift, and they are both lower than Go. That seems to mean that people are writing more Go programs than iPhone apps, and there sure are a lot of apps around these days. I am guessing there are a lot of confounding factors that lead to search volume -- go users are going to "go doc foobar", which Google does not track. Java puts the name of the programming language in nearly every error message, which people often type into Google. While these do not affect the trends (Java declining, Python increasing), they probably make it difficult to compare the raw magnitudes between languages.
Thanks for this—easier to digest than other posts I’ve seen. The ability to restrict interfaces to specific types is pretty cool (unique?) but otherwise seems like generics as usual, but with a distinct Go flavor. Looking forward to using this and cleaning up some boilerplate!
I do wish people would resist the reflex to overtly digress onto their own favorite programming language in any given programming HN thread. I'm not talking about insightfully comparing two languages; I'm talking about going completely off-topic because you want to talk about your own favorite language.
If this is in reference to my bringing up of C# - I did so in order to talk about whether or not Go has generic constraints which are unique (which would be awesome!). I used C# as an example of a language that has constraints that are the same as/as powerful as those in this Go proposal so as not to be making an unsubstantiated claim.
OP specifically said the constraining mechanism was unique, hence why GP (and myself) are curious about what makes it more interesting/powerful than what exists in other languages like C#.
Looks a lot simpler than contracts... I'm much happier with the aesthetics of using interfaces for generic constraints. Looks a lot simpler to use. Besides, it's completely compatible with existing code, only a minor update will be required. Seems to me to be one of those features people will ignore if they don't want but love in the instances where there would otherwise be lots of boilerplate and/or generated code.
I didn't pay much attention to the contracts proposal; is this just simpler because dynamic dispatch is vaguely similar to static dispatch, so it uses one syntax construct (interfaces) to denote both? I'm not opposed to this, but these aren't "interfaces" even though they use a similar syntax, notably the "constraining to a set of types" is supported for constraints and not interfaces.
The thing I worry about the most is that Go without generics works very well for 95-99% of code. The code is very clear and not overly abstract. The remaining 1-5% of code is hard to write in an efficient, type safe, and DRY way, but I don't see how we can have generics and clear, appropriately-abstract code. I strongly suspect this will change the quality of the ecosystem for the worse. I don't think people consider this tradeoff very often.
> I don't think people consider this tradeoff very often.
Every single time generics in go is discussed, a sizeable fraction of the comments are FUD about go inevitably turning into Boost. People consider the tradeoffs often, but in a superficial and dogmatic way based on language tribalism rather than actually looking at the proposal in detail and actually considering the tradeoffs.
You've misunderstood the debate. The concern isn't about Go turning into Boost; it's about Go becoming multiparadigm--about losing the property that "all Go code tends to be written in the same general way" and that people will invariably write code that optimizes for abstraction instead of readability and utility as invariably happens in other languages. If you're not used to Go, you'll probably write this off very quickly because you underestimate (as we all did before we tried Go) how nice it is to have standard, appropriately-abstract code. This is why the debate inside the Go community is more nuanced and amicable--people understand the tradeoff better; they're not shouting uninformed opinions nor pretending there is no tradeoff or that the tradeoff is "just FUD" based on their utter inexperience.
> about losing the property that "all Go code tends to be written in the same general way"
I understand what you're saying but I think (hope?) you're going to be found wrong here. I think that:
(1) very quickly "generic" code will come to be written in a fairly standard way that's accessible to any who cares to spend just a bit of time to know it.
(2) there will be a lot less generic code than concerned Gophers think. I think the generic code will end up in libraries but not so much in application code. Except, of course, in code that uses generic libraries. But using generic code is much more understandable than writing it.
Should be interesting to see how it all shakes out if this latest proposal passes muster. But I think Go will still be much more like "Go" rather than turning into what you dislike about other languages.
This comes across as very patronizing. I've been using go for a couple years now. I'm very familiar with the detailed history of generics proposals in go. I disagree with your characterization and perspective, and continue to see it as simple FUD.
If you were very familiar with the history, you would be well aware that virtually no one is expressing a concern about generics turning Go into Boost. That's a straw man of your own creation. You're welcome to see my characterization and perspective however you like.
I think the proliferation and cultural dominance of Rust finally put a zap on these people’s heads.
Doesn’t matter though. Rob Pike’s smug tone and hubris when it comes to why Go does and does not have certain things is not something easily forgotten. Treating your audience like idiots is one way to grow mindshare among technical people.
There is something to be said for longing for some vague idea or notion of how things ought to work, and philosophies oriented around Plan 9 and BeOS capture this longing very well. But people who actually get shit done - the “programmers” for whom “system programming” languages are supposedly designed for, may not share this sense of nostalgia.
I suspect Rust will be a very costly lesson for them indeed.
Do they even service the same domains though? For me, Go is a faster, more explicit Python. In some domains, it is even more batteries-included, especially where I use it - backend development. It has a great balance of ease of development, deployment, and performance.
Sure, it was billed as a systems language at first, and it saw some traction there (Kubernetes, Docker, etc), but IMO, it sits halfway between Python and C, and it's a language I'm quite happy with for the most part.
I think people confuse it with low-level language, which Golang is not of course. That people normally agree with their prejudices, doesn't necessarily make them correct.
it doesn't matter what we say, Go is owned by Google and what they decide is the Alpha&Omega, everything else will be silenced, banned, ridiculed, ignored, closed, deleted. And in my case, my Adsense sites suddenly having "policy violations" after 14 years of existence and pages being removed or deranked from the Google index.
Be careful what you say because those powertripping ivory tower elitists will destroy your business if you have any earnings from a partnership with one of their products.
I'm willing to be if I had GCE containers they would also have magical errors appearing just in the moment when I DARED suggest they revert a font and they change their "brand" because it's soulless and has nothing to do anymore with the spirit that made Go popular, simplicity and readable code.
Oh and of course one corrupt organization washes the other's hands. Your github account will get flagged without notice or reason given and inquiries will remain unanswered by Github.
Corrupt bastards is what the Go developers are.
Go is not your (as in mine, ours) language. It's a language owned by a corporation that turned evil, that spies on all of us and hands out data to governments.
An evil corporation that cooperates with totalitarian regimes, because their mindset is similar anyway, so what's the deal, right? All just business as usual. Screw the public, we own the place.
.|.. Google and the Go developers
I feel the lack of additional type arguments on methods will be considered a mistake in the longer term. Although the way it's designed it can be added in additional revisions but considering it's taken rather a long time to get here, I don't hold much hope for it landing for some time.
Attempting to define a generic Map function turns out to be somewhat troublesome[1]. This would be really painless if you had type arguments, instead, we have to define an interface to allow peeping into the type and creating a type from a zero value.
Don't get me wrong, I do applaud the efforts for better type system, it's just a weakness in the proposal.
I’m ignorant to golang’s generics saga, but I’m painfully familiar with Java’s (to the point where I wasn’t overly sad when golang didn’t have them). Can anyone explain what golang is doing better?
Go is designing generics around the language tenets, which are quite different from Java's. In themselves, generics aren't particularly interesting...it gets interesting when you start considering the tradeoffs you need to make in order to align them with the tenets of your language, runtime, and ecosystem. I wouldn't say Go is doing generics "better", they are doing them "differently" to align with the goals of the language.
(Personally, I'm not looking forward to generics in Go, I enjoy the simplicity of not having them and haven't encountered situations where they'd make a huge difference.)
I have to agree with other commenters that the syntax leaves something to be desired. A lot of parentheses competing for attention.
Perhaps we could take a leaf from the Modula-3 book — Go was influenced by Modula-2, which didn't have generics — and be more explicit in declarations. I feel this would be more in the tradition of Go.
For example, instead of
func Max(type T Comparable)(a, b T) T {
if a > b {
return a
}
return b
}
This could instead be enveloped by a "generic" declaration like so:
generic T Comparable
func Max(a, b T) T {
if a > b {
return a
}
return b
}
While skimming, I find the article-examples largely unreadable compared to idiomatic Go. You'd almost require generic-aware syntax highlighting in order to grok complex syntax, which breaks normal readability.
Experimenting with wrapping as you suggest, seems a good way to see if that separates concerns in syntax enough to make generics "fun again". Programmed for long time in C++ w/templates . Any and everything that avoids the hells of those syntax and compiler error/messages, could even be called innovative if hitting the right spots. I see generics as convenience, but only if the costs doesn't accumulate over time * complexity.
Generics need to be something natural, not bolted onto a language, or sneaked in. Unlike precompiler defines, and templates to some degree. To that end, maybe it deserves its own nomenclature, form and space, to properly distinguish those special cases from more concrete cases of syntax. Just like we distinguish looping with "for".
Agreed. To keep Go simple and keep it from descending into the kind of extreme generics that Rust practices (nothing wrong with it, but it seems antithetical to Go's simplicity), the idea behind my syntax suggestion is to think about monomorphization as an explicit concept.
You're basically telling the compiler to generate new versions of the same function, or struct, or whatever. The mental challenge with just adding type parameters is that you're thinking of the type as generic, which creates "what colour is my code" distinctions; either types are generic or they're not.
I had another syntax in mind that would reuse the "for" keyword:
for type T:
func Max(a, b T) T {
...
}
Both syntaxes work fine for other declarations; structs and methods, for example:
for type T:
type Atomic struct {
v T
}
for type T:
func (a *Atomic) Get() T {
...
}
Of course, you still need some syntax to specify types in expressions, but that's also solvable.
Parametric polymorphism should probably be very syntactically distinguishable from imperatively looping with "for", though you'd need constraints and multiple types for sure.
The problem from the start with such kind of programming, is that once you start meta-programming, there's always a bunch of stuff you could be missing or adding to the implementation. Just right up to the point where you could be implementing or self-referencing the language in the meta-program itself, or vica versa. But doing this without adding too much complexity for normal everyday use, would either be genius or a failed attempt at keeping things easy.
So I'm sure many are investigating all the use cases what the target should be. Though the end result should still be easy, readable and otherwise clearly distinguishable from other idioms of the programming language.
With a 'generic' interface declaration we could remove the (type T) annotations. The compiler would still know what type parameters are needed (because they are used in the function prototype.)
// generic works like an interface
type T generic {
comparable // generic allows additional constraints
}
// we know the type parameters by the use of T
// (because T is generic type)
func Same(a, b T) T { ... }
// calls may still need to include the type parameters,
// but type inference will generally make them unnecessary
s := Same(type string)("hi","howdy")
s := Same("hi","howdy")
I like the idea of using special syntax to denote the type — $T signals that it is a higher-order placeholder. It means there's no ambiguity to the reader or the compiler.
It also means that for a function that requires no type constraints, nothing more is needed:
func WorksWithAllTypes(val $T) {
...
}
I don't like the type constraint syntax, though. I think it could be done like this:
func Max(a, b $T Comparable) $T {
...
}
The idea here is that we only need to annotate the first instance of $T; all others will implicitly share the same type constraint.
58 comments
[ 4.5 ms ] story [ 143 ms ] threadWhile this is a subset of "new data structures", I'm really looking forward to generic immutable structures that can be read by many goroutines but have some coherent update story. I've got several places in my code where I have a structure I want to update infrequently and have read access in a lot of places, where I'm reading it enough that a traditional read/write lock is a real problem. I've got some stuff hacked together but what I have can't be shared as a library, and I shouldn't anyhow, because a real library ought to be stronger and better.
(I recognize that Go doesn't have immutable data types, but I was programming in Python for many years before Go and have made my peace with "Just don't do that.")
Libraries that operate on maps and slices in a type-agnostic manner.
Probably some numeric libraries with nicer types than you can get now, though I still think Go will be a bad choice for highly numeric code even post-generics.
Several hundred map/filter/reduce libraries that nobody will use for very long.
Data structures are the one I'm really looking forward to, though. Network servers, nominally Go's wheelhouse, is one of those places that we tend to like some obscure data structure choices because of the performance needs. It has been a frustrating hole in the language for a while.
You should watch the Hype Cycle very carefully with Rust. Rust is no doubt on its way to a Plateau of Productivity, but right now we're at the point where "My company only uses Rust!" or "I rewrote my foobarlang app in Rust!" will get you to the first page... but "Wow, my CI system spent 387 CPU days building my Hello World app last week!" is also starting to show up (on its way to the Trough of Disillusionment).
I hate when things fall into rigid categories because it seems overly simplistic, but the Hype Cycle is spot on. Look for it and you'll see it everywhere.
Again, you have to understand that HN's biases play into this effect. There are many people here that want to be at the forefront of the field, but are outraged when they have to show up at an interview and code up a data structure on the whiteboard. If generics were in Go, then someone else would have already written the data structures, and they could continue to believe that the practicing programmer has no need to ever look at a computer science textbook. But the reality is, when you use Go, sometimes you have to show up and write an algorithm or a data structure. (The most common one I've written is an ordered set; a slice with the keys, and the keys and values in a map.) So you can see why emotions are going to run high. Two ideals are in direct conflict -- and generics are going to solve the emotional problems. Thus, much is said and argued on these topics.
I have to say, I sleep way better at night knowing that the Go team is around to deal with all this stuff. There is a lot of arguing and strong emotions, and they sort through it all and continually produce something that seems sane. Because they do such a good job, I don't have to feed the hype cycle, I can sit here and enjoy the view from the Plateau of Productivity.
I'm writing as a regular Go user who's found it very productive, tho I'm worried about its future
[1] https://trends.google.com/trends/explore?date=today%205-y&q=...
[0] https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...
The thing I worry about the most is that Go without generics works very well for 95-99% of code. The code is very clear and not overly abstract. The remaining 1-5% of code is hard to write in an efficient, type safe, and DRY way, but I don't see how we can have generics and clear, appropriately-abstract code. I strongly suspect this will change the quality of the ecosystem for the worse. I don't think people consider this tradeoff very often.
Every single time generics in go is discussed, a sizeable fraction of the comments are FUD about go inevitably turning into Boost. People consider the tradeoffs often, but in a superficial and dogmatic way based on language tribalism rather than actually looking at the proposal in detail and actually considering the tradeoffs.
I understand what you're saying but I think (hope?) you're going to be found wrong here. I think that:
(1) very quickly "generic" code will come to be written in a fairly standard way that's accessible to any who cares to spend just a bit of time to know it.
(2) there will be a lot less generic code than concerned Gophers think. I think the generic code will end up in libraries but not so much in application code. Except, of course, in code that uses generic libraries. But using generic code is much more understandable than writing it.
Should be interesting to see how it all shakes out if this latest proposal passes muster. But I think Go will still be much more like "Go" rather than turning into what you dislike about other languages.
Doesn’t matter though. Rob Pike’s smug tone and hubris when it comes to why Go does and does not have certain things is not something easily forgotten. Treating your audience like idiots is one way to grow mindshare among technical people.
There is something to be said for longing for some vague idea or notion of how things ought to work, and philosophies oriented around Plan 9 and BeOS capture this longing very well. But people who actually get shit done - the “programmers” for whom “system programming” languages are supposedly designed for, may not share this sense of nostalgia.
I suspect Rust will be a very costly lesson for them indeed.
Sure, it was billed as a systems language at first, and it saw some traction there (Kubernetes, Docker, etc), but IMO, it sits halfway between Python and C, and it's a language I'm quite happy with for the most part.
https://en.wikipedia.org/wiki/Systems_programming
I think people confuse it with low-level language, which Golang is not of course. That people normally agree with their prejudices, doesn't necessarily make them correct.
Interestingly, Rust, (Nim,) and Swift are listed under systems programming languages, while Go and Kotlin are not.
Go is not your (as in mine, ours) language. It's a language owned by a corporation that turned evil, that spies on all of us and hands out data to governments. An evil corporation that cooperates with totalitarian regimes, because their mindset is similar anyway, so what's the deal, right? All just business as usual. Screw the public, we own the place. .|.. Google and the Go developers
Attempting to define a generic Map function turns out to be somewhat troublesome[1]. This would be really painless if you had type arguments, instead, we have to define an interface to allow peeping into the type and creating a type from a zero value.
Don't get me wrong, I do applaud the efforts for better type system, it's just a weakness in the proposal.
1. https://go2goplay.golang.org/p/P7CVwOW9wig (note this panics currently)
(Personally, I'm not looking forward to generics in Go, I enjoy the simplicity of not having them and haven't encountered situations where they'd make a huge difference.)
I have to agree with other commenters that the syntax leaves something to be desired. A lot of parentheses competing for attention.
Perhaps we could take a leaf from the Modula-3 book — Go was influenced by Modula-2, which didn't have generics — and be more explicit in declarations. I feel this would be more in the tradition of Go.
For example, instead of
This could instead be enveloped by a "generic" declaration like so:Experimenting with wrapping as you suggest, seems a good way to see if that separates concerns in syntax enough to make generics "fun again". Programmed for long time in C++ w/templates . Any and everything that avoids the hells of those syntax and compiler error/messages, could even be called innovative if hitting the right spots. I see generics as convenience, but only if the costs doesn't accumulate over time * complexity.
Generics need to be something natural, not bolted onto a language, or sneaked in. Unlike precompiler defines, and templates to some degree. To that end, maybe it deserves its own nomenclature, form and space, to properly distinguish those special cases from more concrete cases of syntax. Just like we distinguish looping with "for".
You're basically telling the compiler to generate new versions of the same function, or struct, or whatever. The mental challenge with just adding type parameters is that you're thinking of the type as generic, which creates "what colour is my code" distinctions; either types are generic or they're not.
I had another syntax in mind that would reuse the "for" keyword:
Both syntaxes work fine for other declarations; structs and methods, for example: Of course, you still need some syntax to specify types in expressions, but that's also solvable.The problem from the start with such kind of programming, is that once you start meta-programming, there's always a bunch of stuff you could be missing or adding to the implementation. Just right up to the point where you could be implementing or self-referencing the language in the meta-program itself, or vica versa. But doing this without adding too much complexity for normal everyday use, would either be genius or a failed attempt at keeping things easy.
So I'm sure many are investigating all the use cases what the target should be. Though the end result should still be easy, readable and otherwise clearly distinguishable from other idioms of the programming language.
What would instantiation of the function look like?
With the current design it is
which has a positional symmetry to the declaration.It also means that for a function that requires no type constraints, nothing more is needed:
I don't like the type constraint syntax, though. I think it could be done like this: The idea here is that we only need to annotate the first instance of $T; all others will implicitly share the same type constraint.as for constrains, say if we use decorator, then since T has to adhere to one interface only, func Max from your example could become
[1] https://groups.google.com/forum/#!topic/golang-nuts/Rp3yUUy2...