But even so, even with all the shortcomings, once Java 5 was released people migrated to usage of generics, even if generics in Java are totally optional by design.
My guess to why that happens is that the extra type safety and expressivity is definitely worth it in a language and without generics that type system ends up staying in your way. I personally can tolerate many things, but not a language without generics.
You might as well use a dynamic language. Not Python of course, but something like Erlang would definitely fit the bill for Google's notion of "systems programming".
The Go designers are right to not want to introduce generics though, because if you don't plan for generics from the get go, you inevitably end up with a broken implementation due to backwards compatibility concerns, just like Java before it.
But just like Java before it, Go will have half-assed generics. It's inevitable.
Personally I'm sad because Google had an opportunity to introduce a better language, given their marketing muscle. New mainstream languages are in fact a rare event. They had an opportunity here to really improve the status quo. And we got Go, yay!
I've mostly moved on to Clojure for programming backend services. I still use Go for the occasional small utility program due to its speed and ease of deployment, though.
I've never once even considered the fact that I might need generics because I've never run into an unsolvable problem or an extremely inelegant engineering solution. I see a lot of people claiming that the lack of generics is a big problem but no one is actually showing a concrete case where generics are necessary.
C doesn't have generics but we never have this discussion when we talk about C.
That is a trivial example where generics help. And yes, the endless boxing and runtime type assertion does make your code slower eventually (see the comment from the libcuckoo authors).
This is one of the reasons why the container and sort stdlb libraries are such a joke. They're not generic so they have to special case every different type. With generics, the entire sort package would just be a function that takes Ordinal and sorts it. Container would similarly only require one implementation of each data structure (because they would be generic).
I find it hard to believe that you've programmed "scores of Go" and you've never hit any of these issues. I also have programmed plenty of Go, and these problems are just frustrating.
But again, I still severely doubt you've never run into a problem with Go's lack of generics. I ran into it after about 3 months of working with Go. Maybe you didn't find the work-arounds problematic, but that doesn't mean that the original limitation (no generics) doesn't cause problems. You just choose to accept the work-arounds as the "right way" of doing things.
If you haven't already, I would recommend looking at Rust or another modern language that has generics to see what sort of benefits you can get out of it that you can't directly get with Go. Personally the fact that if T implements an interface I won't let you use T as I is pretty silly IMO. Rust lets you do that with the From trait, and you can even do it even more generically with the From trait using a generic T.
Sure it does, a light weight version was introduced in C11.
Besides, C gets an excuse because the language was designed before generics were even invented, and with pre-processor macros is it possible to implement a poor man's generic system.
So, at runtime, Go 1 code needs to be able to work with Go 2 types. That will impose some restrictions, I imagine.
Interesting. Are there any other languages where that is allowed? I'm assuming that by "codebase" you mean all the code that gets compiled into one program or library (for compiled languages), or is part of one program or library (for interpreted languages). And I don't mean the case where only a common subset of Lang X v1 features and Lang X v2 features are used in the same codebase (because in that case, there is no issue). That latter case is possible, for example, in Python, and probably some many languages too. In fact by the definition of the case, it should be possible in all languages.
>>Interesting. Are there any other languages where that is allowed?<<
C / C++
The various language feature pragmas in Haskell.
> Are there any other languages where that is allowed?
One would be Racket, a Lisp which allows you to pick a syntax flavour using the #lang directive: https://docs.racket-lang.org/guide/Module_Syntax.html#%28par...
Use site variance can be really powerful when you're dealing with invariant data structures like Lists. You can then treat them like covariant or contravariant depending on a particular method call at hand.