Some people judge the language on their ability to get work done with it.
I get generics, but they really don't come up in daily use with the tasks where I use Go. Yes, it would be nice for writing some libraries but you're going through a laundry list of Rust features which don't hamper my ability to get work done at all.
I even like Rust, but if I'm going to write a worker that will read from a queue, do a transformation and write to a few more queues/services upon completion, Go just works and the turn around time is far better than Rust. It's like was Perl was for Unix, but for the cloud instead.
I wrote a bunch of Rust, Scala, Haskell, but I still greatly prefer Go, even without generics.
I am very happy with the generic container libraries I'll get with generics, but I hope people won't try to be too clever (as they usually do). So far, Go is a language that just rules out a lot of bikeshedding, which I very much appreciate. We'll see how that evolves.
I do think premature or wrong abstractions are a much bigger and widespread problem than a lack of abstraction.
Also, I really like Go's error handling, it results in error messages in Go projects usually being top-notch (because of explicit handling and wrapping which includes relevant context and human-readable messages).
I remember listening to a podcast about C++, and the guest explained how after working with C++ for about five years, they still encountered aspects of the language that surprised them on a regular basis (to be fair, though, that was before C++11). To me, Go just clicks in way few languages did.
While I applaud the focus on simplicity, I found it simply transfers that burden to the programmer (I have to loop over a map to clear it...really?). Every single "lack of" feature in Go (has nil, no sum type errors, no pattern matching, etc.) is in Rust which gives me endless freedom to express safe, correct programs. I suppose language choice is highly individual, but it still perplexes me as to what people see in Go over Rust.
I have a lot more fun writing code in other languages. I enjoy not having that burden on me while writing code. In an earlier life that would have been important to me. Now that I'm old and curmudgeony I've started to value other things.
I can teach any mook with basic Java/C# programming knowledge how to be productive in Go in less than a week. At this point they can read pretty much any Go code pretty fluently and can be trusted not to commit anything stupid.
Can you say the same about Rust?
get_data() { filename=default ... }
=becomes=>
get_data(filename=default) { ... }
When the type either does not matter, but the concrete instance records it, or the type makes sense to be configurable, you want generics. As a silly example (but short enough to fit into a comment block): fn nth(seq: [int], n: int) -> int
Now you have to make a new nth for every single sequence type, even though it has no bearings on the actual operation. Or you make it generic: fn nth<T>(seq: [T], n: int) -> T
That's a trivia case, yes. But if anyone has ever worked on a complex code base there are plenty of situations like this that turn up, at least in my experience. Sure, I almost always start off with concrete instances with a fixed type, but as soon as it becomes apparent that the type itself is irrelevant and I have a couple use-cases with different types, why not make it generic and be done with it? Like, would you really have more than one version of that get_data function running around, one for every conceivable filename? That would be obscene. Why would you do the same with types?There is a reason why even in mathematics people like to operate on concrete examples to get an intuition. For many, concrete is much easier to understand than abstract.
That's the less important point. The more important point is that making your code generic often involves more trickery which makes the code more complex, even if you only use the code once or twice - so that's just effort wasted.
The fact that parameterization is a proven abstraction doesn't mean it's good everywhere. Same as I don't agree with the "Clean Code" way of creating a myriad of 4 line functions.
Yes, good programmers won't make these mistakes, you can totally handle them. But when arriving at legacy code or open-source projects I greatly prefer to find under-abstraction rather than over-abstraction.
To be clear, I'm not against generics, I just agree with the parent of my original message. I'm worried people will overuse them and I don't want a whole laundry list of Rust features in Go. I'm very happy about libraries with type-safe generic B-Trees.
I sort of understand this argument, but I can't really imagine defining queue as something else then <T> wait_for_item() -> T. I've been writing Python for to long to know that wait_for_item() -> any will backfire in production eventually and I don't want that. At some scale (both in code size and amount and scope of dependencies) those problems just become too serious and too common to not have language that deals with that. And Go is way too popular for people to limit its use only for the cases where it currently works.
A specific queue is typically well defined and has a struct in/out.
There are times when I've wanted arbitrarily nested JSON that doesn't map into structs very well, but it is uncommon enough.
Since the inception of async/await in Rust, it is incredibly quick to whip something like that up. The slowest part might even be the time it takes to compile. Maybe that's what you were referring to?
Really? Safety and correctness aren't relevant for you? Then why even bother with go instead of Python or a Lisp?
For me it's crucial that a programming language contains tools that allow me to definitely rule out as many errors as possible. A powerful (and sound) typesystem does just that.
If you want to definitely rule out as many errors as possible, dependently typed languages are the state of the art, allowing you to write a sort function that will fail to compile if it returns a list that isn't sorted (eg,https://dafoster.net/articles/2015/02/27/proof-terms-in-idri..., or https://www.twanvl.nl/blog/agda/sorting).
After all, if you can't even prove basic properties about your code from your language, like array accesses being within bounds, are you really using all possible tools to rule out errors at your disposal?
Otoh, I do know that languages like OCaml, Haskell, or Rust take the burden of trivial errors from my shoulders for neglible cost.
Same with every other thing that goes into this language. A thing that's been available elsewhere for literally 3-4 decades.
We have some examples in this very thread.
> Really? Safety and correctness aren't relevant for you? Then why even bother with go instead of Python or a Lisp?
A charitable reading of the GP would be that "safety and correctness" would be included in "getting work done", in amounts that are appropriate to the work in question. Your interpretation is... less than charitable.
Perl and Go both have the kind of long-term language stability that I value above all.
But Go offers excellent concurrency, networking baked-in, and now even fuzzing.
I value maintenability (type safety helps prevent unintended consequences) and readability (Haskell and Clojure are out).