- Lack of generics(coming very soon) was a huge problem for a long time and resulted in masses of duplicated code, and shonky reimplememtations rather than battle tested reusable implementations.
- Lack of sum types, which is particularly frustrating with go's error handling model (which I happen to be a fan of, mostly). The state of a return value depends on another return value in many cases. There is nothing in the language stopping me from using the value returned from a function that has returned an error. Even c++ has a (half baked) solution for this with optional.
- go's error handling has a major issue; it forces my model to be able to represent invalid state (see above). Because go doesn't let me have a sum type, I'm forced to return a "valid" return value alongside the error value, which means that state has to be representing in my code.
- repetition. Contrary to best practices in every other programming language, the advice given for go on so is frequently "its not that much work to implement the X yourself". Now instead of using an existing well supported library I'm maintaining my own X.
- cgo. Performance is terrible, its completely unique compared to every other FFI style system (e.g. see dotnet), and it doesn't work with MSVC.
> that took into account & understood the practical tradeoffs Go is making.
Just because the language had made decisions because of tradeoffs doesn't make it immune from criticism. If it's OK to criticise c++ for not breaking backwards compatibility (vector<bool> comes to mind), it's OK to criticise go for its shortcomings.
I never said it was immune to criticism. I think most of the criticism is misguided.
>- go's error handling has a major issue; it forces my model to be able to represent invalid state (see above). Because go doesn't let me have a sum type, I'm forced to return a "valid" return value alongside the error value, which means that state has to be representing in my code.
I recognize that this does not perfectly map to your mental model, but why is this a major issue? I think major issues are those that cause practical problems.
I also think there is a question of what the cost, in terms of developer cognitive load, would be of adding more advanced modeling features to go.
It's a bit like saying "that tire isn't perfect because it can pop, so lets use a metal tire instead". Sure, you fix one issue, but you create others.
>- repetition. Contrary to best practices in every other programming language, the advice given for go on so is frequently "its not that much work to implement the X yourself". Now instead of using an existing well supported library I'm maintaining my own X.
This is too vague to evaluate. There is a point at which repetition becomes a problem, and there is a point at which repetition is cheaper than having an abstraction. I don't think it can be evaluated in general.
> cgo. Performance is terrible, its completely unique compared to every other FFI style system (e.g. see dotnet), and it doesn't work with MSVC.
I agree on the factual level that it would be nice if cgo didn't have so much gc overhead. If this is meant to be evidence that go is a bad language, I would disagree.
That's the thing about Sum Types. They're not really an advanced feature at all: they map to an extremely intuitive human concept: "or". They reduce cognitive load. That's the advantage of having them. In fact, I suspect that a lot of the reason that dynamic languages are considered simpler is because every variable is essentially one big sum type. Trying to represent "or data types" without sum types requires you to use interfaces which are a much more advanced language feature, and are very awkward for the use case of a finite number of known cases.
You could have a perfectly functional language with only logical AND (&&) and logical negation (!) and no logical OR (||). It wouldn't cause any practical issues. But you wouldn't: it would be incredibly awkward. Likewise there should be a datatype for OR (sum types) as well as AND (structs/classes).
> I recognize that this does not perfectly map to your mental model, but why is this a major issue?
The phrasing of this implies that it's my fault that go forces me to represent invalid states, not the languages. Here [0] is a 30 line (contrived for brevity) example showing something that is just not possible if you use C++'s std::optional, or Rust's Result types.
> It's a bit like saying "that tire isn't perfect because it can pop, so lets use a metal tire instead". Sure, you fix one issue, but you create others.
Actually I think it's more like saying "A metal band around a wheel is fine, why would we wrap them in rubber, that just causes more issues".
> This is too vague to evaluate. There is a point at which repetition becomes a problem, and there is a point at which repetition is cheaper than having an abstraction. I don't think it can be evaluated in general.
I disagree. Fundamentally the js ecosystem suffers from being too far the opposite (left-pad), and golang swings too far in the repitition direction. Here's some examples of really fundamental things that are missing from the language/libraries, that the response is "just write your own" [1][2][3][4][5]
> If this is meant to be evidence that go is a bad language, I would disagree.
The method of actually interacting with cgo is completely bespoke and novel, and unlike any other FFI system, without any advantages for doing so. It's fair and valid to criticise C++ for it's arcane build system, lack of package manager, lack of abi stability, and name mangling. It's fair to criticise js for it's over reliance on tiny packages, npm and all the extra compile steps it requires for an uncompiled language. It's fair to criticise rust for excruciatingly long build times, therefore it's fair to criticise go for it's half baked slow ffi IMO.
[0] https://gcc.godbolt.org/z/eKWq6rnb7
[1] https://stackoverflow.com/questions/44940822
[2] https://stackoverflow.com/questions/21362950
[3] https://stackoverflow.com/questions/7782411 (no way to iterate through the container itself, only make a copy)
For example, I may dislike a language simply because it has no significant white-space: I just like a programming language to display nicely, for my definition of "nicely". I do understand practical tradeoffs of significant whitespace, yet I still like it: those are not in opposition with each other.
> ...my ideological biases against Go
which you turned into a question of whether Go is a good or bad language. That was never brought up.
An idealogical bias against Go could be that it was conceived by Google, and that you reject to support increasing Google's influence on the world.
This has nothing to do with Go being technically good or bad.
So far as I'm aware, every mainstream language, including golang, that's addressed this question has chosen to solve it by monomorphising generic functions. This implementation was well understood when golang was first released, and it isn't remotely plausible that the authors were not aware of it.
> Also what breaking changes you are talking about I am not aware of any. Also there is no golang 2.0 yet.
An argument given at the time was that committing to an implementation of generics would potentially put golang in an awkward position similar to Java's wherein if the implementation turned out to be bad, the language would be stuck with it anyway for backward compatibility reasons. I am simply pointing out that, since both golang 2 and generics have been discussed roughly contemporaneously (generics landing shortly, golang 2 having first been discussed in 2019 and therefore presumably to happen at some point soonish), any initial implementation of generics would not have particularly constrained what the golang team is now doing.