Go’s shortcoming is also its strength. Language design is a constant battle of tradeoffs. And I happen to find many of the decisions C++ and Rust made weren’t analogous with my preferences.
> It’s still Go’s fault and people rightfully argue that they should prefer a different language.
It’s no more Gos fault than it is the people using Go. It’s called an “opinion” and “preference”. Please don’t assuming your preference is some global truth, because it is not.
Go generics does have this feature. You can require a generic type to implement an interface.
It reminded me of early years of Rust where people saw traits and asked, well Java had interfaces for many decades, what’s the innovation?
You're right of course that traits are more powerful than interfaces. Go simply isn't designed to satisfy fans of elaborate type systems. This can be frustrating at times, but it also means that you don't have to deal with overarchitected library code like this: https://github.com/marshallpierce/rust-base64/issues/213 (Yes, you can overarchitect code in Go too, but the simplicity of the language, and the model of the stdlib, do tend to discourage this in practice.)
I've never written Rust professionally, but I did have a Haskell job for a couple of years. IME the sophistication of the type system is a double-edged sword. Sometimes it lets you concisely express important invariants; sometimes you end up spending way too much time writing elaborate types for code that isn't really doing anything very interesting. I understand the appeal of fancy type systems. In practice, I get a productivity boost from any kind of basic static typing, and then rapidly diminishing returns from the fancier stuff.
The Go language itself is never its strength but it has a good runtime, wonderful standard library and tooling. People never picked Go for being an amazing language, but rather for these other things.