Why Go's Error Handling Is Awesome
rauljordan.com
rauljordan.com
It's so much fun to `return err` through every layer. Explicit no-op attached to every call, yeah!
> No unexpected uncaught exception logs blowing up your terminal (aside from actual program crashes via panics)
A great opportunity to search a code base for logging messages and reconstruct traces by hand. A real true craft!
> full-control of errors in your code as values you can handle, return, and do anything you want with
Yes, it's a real engineering marvel. Exceptions are so bad at this, you could only catch it and, wait...
> Rust, for example, has a good compromise of using option types and pattern matching to find error conditions, leveraging some nice syntactic sugar to achieve similar results.
Thank you for mentioning Rust, I guess. It's very saddle not to include `try` on the table.
Yeah, this one jumped out to me, too. I like exceptions in my logs when something unexpected happens.
In other words, Go's error handling is an even less ergonomic way to do checked exceptions than Java's checked exceptions.
I'm of the opinion that Java was right all along and they just didn't have the inference tools to make it ergonomic at the time, but I'm in a tiny minority there, and most of this article could have been swapped out as a defense of checked exceptions, while the rest is a subjective defense of the syntax.
And then there are the things that checked exceptions give you that Go's errors don't:
* Automatic stack traces. No need to decide that the error is "actionable to developers" and remember to load a library and wrap the error, errors have stack traces. I can't emphasize this enough.
* You can opt out of the line-by-line exception handling by just declaring that your function can throw. The line-by-line manual handling is only valuable in cases where your functions are very long and might throw many errors (problematic for other reasons) or if you don't have stack traces and need to piece line numbers together by hand (see above).
There are other flaws in Java's implementation, but it's been very frustrating to see how many of the new languages just reinvented Java's checked exceptions but worse instead of iterating on them.
Surely, if Go's method of error handling is superior to every other programming language, there must be some meaningful statistical side effects that can be observed to prove it right? Lower rate of runtime errors, faster time to debug errors, etc. Someone out there in academia must have been able to actually measure this effect if it exists?
If not, can team Go stop going on and on about how superior their excess keystrokes are?
Or do you seek someone to, rather than prove one screwdriver is less error prone than another, to demonstrate it is?
If so, that would depend on context of screws, wood, lefthandedness. A proof in a special case is especially limited. So a demonstration.
Can you demonstrate Go's method of error hanling for a specific context is superior? Yes, you can.
These are all measurable. Productivity is measurable. Defect rates are measurable. Time to debug is measurable.
If there's a peer reviewed paper, let's see it. If there's not, you should produce it and get hired by the Go team!
If this is indeed the superior way of handling errors:
varFoo, err := GetFoo()
if err != nil {
return err
}
and not just excess key strokes and preference of style, then there will be some statistical side effect that can be measured to prove its superiority. If you can't prove it, all you're saying is "I prefer purple because purple is obviously superior to blue! Can't you see!"...O...K.> Can you demonstrate Go's method of error hanling for a specific context is superior? Yes, you can.
Then please do! Articles like this one are entirely subjective and anecdote-oriented, not evidence-based proofs (or demonstrations if you like).
Have you seen many of those?
Aside from this it's probably quite difficult to measure! Sure there are a bunch of metrics you can capture, but unless you're really doing a randomised controlled trial, you will have an absolute dog's breakfast of confounded observational data - good luck getting much useful out of that.
I don't think it would be hard to measure at all.
Randomize some CS students into Go and non-Go and see which teams produce projects with lower rates of defect and faster time to submission. Try it with teams in enterprises; I'm 100% certain that this kind of statistical evidence is meaningful to some CTO/CIO somewhere. Prove to the entire world that everyone should be using Go because it will lead to cost savings not just in time to market, but also less downtime and defects. The financial benefits would be enormous! Possibly billions if not trillions of dollars of productivity gained, system downtime avoided, and runtime defects eliminated ("what runtime defects?") because of the inherent superiority of:
varFoo, err := GetFoo()
if err != nil {
return err
}
Billions!So that doesn't seem like a good metric to determine if Go's error handling is "better" (in some dimension) than other techniques.
If Go is a superior programming language -- error handling or not -- it should be easy to find the statistical evidence. Otherwise, you just prefer green crayons; please, by all means, go enjoy your green crayons.
Go's error handling isn't any better or worse; it's just objectively way more verbose. With what benefit? If you wish to claim one beyond your subjective vibes, please by all means prove it with evidence.
I'm not claiming any benefit by the way of Go's error handling. I've never even used Go. Just pointing out that measuring defects is not a good way to determine whether it is or isn't.
> It was specifically about whether the error handling aspect is better.
If it's better, how? Can you prove it? Does it lead to lower defect rates? Lower time to debug? Less runtime errors? How is it better other than your preference of green crayons?Measuring defect rates against another language will not tell you whether the error handling is better or worse than the other language either.
Using students still has problems - have they coded before? Have they worked in a team with industry-style review processes before? The population you're sampling is quite different to experienced software engineers. It's not quite "...in mice" levels of qualification needed, but it's fundamentally the same problem.
> Try it with teams in enterprises; I'm 100% certain that this kind of statistical evidence is meaningful to some CTO/CIO somewhere
Difficult again - how do you do a fair comparison? You'd need to be doing fair randomization - in particular as soon as anyone gets any say in which team uses what language for which project, you have a good chance of stuffing things up. Is one of the projects more important to the business, so is likely to get a "better" team allocated to it? Does one of the teams have a language preference? Does the business have a language preference? Is one of the projects well-suited for Go (say a web server) and the other terrible? (say a desktop app)
One approach might be to get two teams to build the same thing and one gets thrown away, but what CTO is going to pay for that once? Let alone finding enough to pay for a big enough sample size to make anything of.
I'm not trying to get into fights about languages, I'm trying to make the point that actually making an objective measurement like you suggest is really, really difficult.
> Using students still has problems - have they coded before?
Why would it matter if we're doing randomized experiments with students placed in groups of different languages? That's how randomized experiments work: it doesn't matter if they've coded before because the selection process will randomize a statistically relevant number of students.> Go's infamous error handling has caught quite the attention from outsiders to the programming language, often touted as one of the language's most questionable design decisions.
> Although it may seem redundant and unnecessary for those new to the language
I have plenty Go experience, yet think the lack of sum-types is iffy. But I don't identify as a true-blue "gopher" so I guess I must be an outsider that just doesn't get it.
Any design that doesn't actually force you to handle the error case cannot be called good in my opinion.
if err != nil {
<do stuff>
}
after nearly every function call and to have a error as a secondary return type. At least for me it is clunky and annoying and incredibly distracting. If there was at least some syntactic sugar around this I could probably live with it but like this I just don't like using Go.if res, err := doSomething(); err == nil { return nil, err }
no point in continuing with a null object anyway
ASSIGN_AND_RETURN(auto var, status_or);
And RETURN_IF_ERROR(status);
Which are just more ergonomic with the drawback of being macros.Go error handling is literal garbage compared to things like OCaml's Result plus anonymous unions, or Haskell and Rust's Either and Result.
return "", err
each time. Then if you introduce another return value, you need to edit a ton of lines to also return a value for that one, typically just to return the default of each along with the error. Not only is that annoying, but it's prone to carelessly returning something non-default along with the error due to copy/pasting. But complaints aside, I agree with the article that Go's error handling is pretty awesome.Albeit it transfers repetition from one place to another.