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.
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)
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.
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.
Huh? First they said they would: https://youtu.be/rKnDgT73v8s?t=3267 After a decade of nobody coming up with a solution that did turn to believing that Go would never be able to add generics. That is true. The air of defeat did become quite strong. But the Haskell guy did eventually came along to share his expertise and the rest is history.
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.
Java started as a language to write apps on the Internet (applets). Then, it evolved into an elephantine corporate-focused language, because that's where the money is. I remember those Java applets that took minutes to load. The Web was taken over by JavaScript instead, which was famously coded in ten days.
Go used very particular shortcuts to make its GC'd runtime lightweight enough and the language simple enough. But, due to Conway's law or something else, it was destined to become a corporate-focused elephantine language, gradually.
I remember 10 years ago I believed that Go lacked something like STL. Later I changed my opinion cause I started to realize how much overhead red-black trees and suchlikes introduce. Especially in GC'd systems. This abstraction Jenga may indeed look shockingly absurd when you see all the moves in the system, not just your layer.
In performance-critical cases, I personally use ABC, a C dialect with solid containers. Those are basically chunks of RAM with fixed-bit-layout records in them. Vectors, hash maps and hash sets, heaps and queues are all just arrays. If we only needed that, we might have stayed with C. Solid containers require no malloc() and no GC. Can mmap them and you have a database. Can send them over the network as-is. That is the ultimate 80/20 thing here. LMDB is another example.
But if you keep adding features, 80/20 is no more and your Go becomes an uglier Java or Rust.
Language is more than just its syntax and features.
The most important "features" of Go are fast compilation, orthogonality of features, and easy development.
Their propositions may "look like everyone else" if you're only looking at surface syntax, but there's a reason why it took 10 years to design an acceptable generics proposal, and the result is that compiling generic-heavy code is almost as fast as compiling plain Go.
Go being strict about features it accepts is not an ideological thing, but a practical one. If Go could have all the features in the world while still being easy to use, fast to compile, and internally coherent, it would. But it can't (see: C++, C#, Python).
On the other hand, I've found that for every real-world application I've written in Go, I have not found myself missing any of the containers C++ has had since 2003. I didn't really ever need generics either. I only use them to make it to make it clear which functions don't rely on specific properties of the type they operate on.
Yes, there are occasionally really good reasons to use an ordered map or a priority queue, but I haven't needed either in years.
Or it’s just people with different opinions that took charge.
I find it funny reading sometimes how my country learned to conform on something that was previously a bit unique and people are like ”yeah, even they figured out it doesn’t work!”. No, you dingus, the people that wanted to conform were just elected. It worked perfectly fine otherwise.
Welcome to Java, where Collections are the bread and butter of every programmer since 1998.
While you are at it, I humbly suggest to add composable streams too, that we had in 2014, and that make working with collections way more pleasant.
(Jokes aside, in Java it is very nice that you can start with a generic ArrayList and turn it into a linked list with one single keyword change and no code needs changing, or that you can turn any collection into a synchtonized or readonly doppelganger with one line of code. Collections are nice and I miss them in Golang)
It's cool that they're doing this but with iterators and soon in 1.27 generic method parameters, you can already DIY most of this with little effort. I've got iterators at work for nearly everything I could want, small libraries for extra mapping, filtering etc operations, and with agents going back and actually refactoring old code to use them is easier than ever.
I find it so sad that people wasted millions of hours and lines of code rewriting over and over basic constructs that should have been on the language in the first place. How many years before we finally get sum types?
> Since the addition of generics in Go 1.18 and iterators in Go 1.23, it has become possible for library-defined types to achieve comparable ergonomics to built-in types ...
For those who've been following Golang more diligently than myself: Is there a way now to define a slice-based type that enforces strict typing of its index, and yet preserves the compactness of the standard syntax "s[i]"?
31 comments
[ 0.21 ms ] story [ 31.2 ms ] threadI wish they wouldn’t mix mutation methods in there, but ok.
Go used very particular shortcuts to make its GC'd runtime lightweight enough and the language simple enough. But, due to Conway's law or something else, it was destined to become a corporate-focused elephantine language, gradually.
I remember 10 years ago I believed that Go lacked something like STL. Later I changed my opinion cause I started to realize how much overhead red-black trees and suchlikes introduce. Especially in GC'd systems. This abstraction Jenga may indeed look shockingly absurd when you see all the moves in the system, not just your layer.
In performance-critical cases, I personally use ABC, a C dialect with solid containers. Those are basically chunks of RAM with fixed-bit-layout records in them. Vectors, hash maps and hash sets, heaps and queues are all just arrays. If we only needed that, we might have stayed with C. Solid containers require no malloc() and no GC. Can mmap them and you have a database. Can send them over the network as-is. That is the ultimate 80/20 thing here. LMDB is another example.
But if you keep adding features, 80/20 is no more and your Go becomes an uglier Java or Rust.
The most important "features" of Go are fast compilation, orthogonality of features, and easy development.
Their propositions may "look like everyone else" if you're only looking at surface syntax, but there's a reason why it took 10 years to design an acceptable generics proposal, and the result is that compiling generic-heavy code is almost as fast as compiling plain Go.
Go being strict about features it accepts is not an ideological thing, but a practical one. If Go could have all the features in the world while still being easy to use, fast to compile, and internally coherent, it would. But it can't (see: C++, C#, Python).
Yes, there are occasionally really good reasons to use an ordered map or a priority queue, but I haven't needed either in years.
I find it funny reading sometimes how my country learned to conform on something that was previously a bit unique and people are like ”yeah, even they figured out it doesn’t work!”. No, you dingus, the people that wanted to conform were just elected. It worked perfectly fine otherwise.
While you are at it, I humbly suggest to add composable streams too, that we had in 2014, and that make working with collections way more pleasant.
(Jokes aside, in Java it is very nice that you can start with a generic ArrayList and turn it into a linked list with one single keyword change and no code needs changing, or that you can turn any collection into a synchtonized or readonly doppelganger with one line of code. Collections are nice and I miss them in Golang)
For those who've been following Golang more diligently than myself: Is there a way now to define a slice-based type that enforces strict typing of its index, and yet preserves the compactness of the standard syntax "s[i]"?
Nope, no way to do that.
I wonder about ergonomics. I can imagine "academic" usage, but I shudder at the perspective of the impact on a typical CRUD app.