I’m very open to the idea that I’m suffering from a problem I don’t know I have, but right now you’re just asserting that problems exist without actually telling us how to recognize them.
I’m very open to the idea that I’m suffering from a problem I don’t know I have, but right now you’re just asserting that problems exist without actually telling us how to recognize them.
If anything, I think compiler time is worth a lot less than developer time for the vast majority of projects, and if a compiler pass saves developers even a little time, I say add the compiler pass (within reason--don't keep doing this until the compiler grinds to a halt). This is fairly obvious and encoded into the compilers of almost every compiled programming language. But Go is learning this 12 years into its existence when everyone else knew this before Go existed.
As for goroutines being limited: here's a practical example:
1. Write a basic two-person p2p chat in Go and some other appropriate language. At a high level, each user client has a message log, and the other user can write messages to it. Since the arrays are single-reader, single-writer, there's no real problem, just use an array: this is a nice demo of how simple Go is! You don't need all these fancy abstractions!
2. Expand the chat to include a third person. Again, everybody gets a message log, but now more than one person can write to it. Now, your message log is multiple writer, single reader (assuming each user can maintain their own log of messages they've sent so they don't need to read other people's logs to get those--there's an implicit copy here but that's fine). In Go, start over and write a probably-buggy implementation of a SRMW queue because Go is too simple to have that already. In any reasonable language, wrap writes to your message logs in a built-in queue that's already thread-safe. Note here that "any reasonable language" in this case includes Java (LOL!). In Erlang/Elixir/Clojure, you may literally have accidentally supported a third user already and have to make no changes. There are of course other go implementations which are maybe more idiomatic, but none of them approach the simplicity of a language that supports message passing.
About the second part, you seem to mix up goroutines and channels. In a concurrent system, you would need locks for your example, and channels fix this. Goroutines are just the representation of independent processes and can be implemented and ARE implemented differently per compiler, check e.g. how tinygo and gopherjs do this.
Your example point 2 doesn't make any sense, check fan in and fan out patterns with channels. Go supports message passing, that is what channels are. You really didn't try Go and it shows.
My immediate thoughts are:
- This is rather specific. Not all programs should be using complex thread-safe data-structures. Rather, the primitives are in place to build such things, and libraries can be imported etc.
- These more sophisticated data-structures have runtime costs that are a bit less straightforward to understand as compared to arrays. They require either (a) programmers to be aware of the edge cases or (b) a higher-level language where programmers relinquish some control over runtime performance. To be clear, I personally enjoy many such languages.
Overall, your criticism is equivalent to saying "Go is too low-level". That may well be the case for many applications, but that remains to be argued more precisely.
But I can say that it's the same ad with natural languages. No one ever feels that their mother tongue is limiting, until they learn a new and very different language and learn a pattern/style that they cannot apply in the mother tongue.
- Go
- OCaml
- Python
- Lisp
I think I have a reasonably good sense of what each language offers and what it does not. But OP goes beyond saying "Go does not offer some features that other languages offer"; he effectively says that the language causes severe problems. Where are they?
From my perspective, none of the languages you listed allows for good error handling. But that is obviously only my perspective. I would call this a "severe" issue. In fact, all languages that k I know have at least one "severe" issue.
I guess in natural langages this would be the sapir-whorf hypothesis.
Blub seems like a much stronger effect though, at least anecdotally. But that might be because natural languages are rarely compared in terms of features / capabilities, and even more rarely “ranked” along various such axis.