I think a month of complaining about Go is enough for me, so today will be the last post in this series. You can read the beginning of the series or find links to the rest of the series at the bottom of this post.
We’ll finish up with a couple of quick items and wrap it all up.
Lack of Generics
Omitting generics keeps the compiler fast and reduces the complexity of the language. Fine. I get it. Speed is the goal.
But actually, wait—I don’t care. My goal isn’t compiler speed; my goal is to speed myself up. Repeatedly re-implementing algorithms through copying and pasting or error-prone runtime introspection is the opposite of that. We have fast computers so that we can automate repetitive, boring tasks; let’s use that power in our compiler instead of pushing it off to the poor human.
Plenty of other people have written about this in great detail, so I won’t add more here.
Lack of implicit type conversions
In Go, every type conversion has to be explicitly specified. I’m actually in favor of this in general; just look at the crazy rules and machinery they had to add in C++ to make implicit conversions work “most of the time.” However, one place where implicit conversions should happen is in numeric expressions (as long as everything is signed or unsigned). If I add an int16 and an int32, the result should be an int32, not a compiler error.
The reason this would be useful is because it’s so easy to mix integer types
that should actually be safe together.
sum := 0 gets you an int, and it’s
not at all uncommon to then get back an int32 from a library call. Now if I
want to add up those int32s into sum, I either have to cast each addition or
remember to specifically declare sum as int32. Or maybe I want sum to be
int64 so that it can hold a bunch of int32s without overflow. Well, now I have
to cast every addition to int64 even though expanding int32 to int64 is
completely well-defined and should be the obvious thing to do.
Unlike most of the other complaints in this series, at least this one does have the advantage of penalizing the writer instead of the subsequent reader.
Go has some cool concepts. For example, channels and goroutines aren’t really new, but I think they’re often a way better way to build concurrency than asking programmers to reason through threads.
Despite the cool concepts, I find myself frustrated enough about the warts in Go that I never reach for it as my go-to (har, har) language. Some people obviously feel differently about this and/or have learned to deal with it; there are some massive systems written in Go, and there is a large, enthusiastic community. Nevertheless, I hope that Go 2 (if it ever comes) will find a way to fix some of these problems.
And now it’s time to find another blog topic that doesn’t involve so much complaining!