I've grown to prefer it, as exception handling typically boils down to "not my problem" in most code bases. Go forces you to think through each error condition, which is an unusual amount of effort for people who may not be accustomed to it.
The problem is not that Go's error handling requires more thinking or efforts, it's that it is bad, and while that's an improvement from C's terrible error handling it's still nowhere near good enough, let alone good (unless you consider C's error handling to be good enough in the first place).
There are many cases where this is not true.
I must be missing something.. Returning a value in Go for error signaling is the way to signal errors in Go.
Yes? That's the point, I'm comparing it to more modern languages which signal error "the same way", by opposition to languages implementing different high-level methods of error signaling. The clause is there to explicitly point out that I'm not considering or talking about exceptions and conditions-based error signaling.
Maybe it'd have been clearer if I'd written "languages which also use return values"?
One is that it quickly becomes hard to find out where errors really came from. Consider this idiomatic code:
func MyFunc(input int) (output int, err error) {
if output, err = someOtherFuncA(input); err != nil {
return
}
if output, err = someOtherFuncB(output); err != nil {
return
}
// ...
}
If MyFunc returns an error it's not possible to know where it came from unless you know all about someOtherFuncA and someOtherFuncB and they return different kind of errors.
What's missing from the stdlib is a utility that wraps errors to reproduce what's essentially a backtrace. `return wrapError("someOtherFuncA", err)`The other issue is that (error) doesn't tell you what kind of errors are going to be returned. It's often useful to be able to classify errors as to respond to them accordingly. IO errors might be retryable but data-structure errors might be not. In the stdlib they use value comparison as a trick to classify errors combined with documentation of what exactly will be returned.
I've written code with this style of error-handling in Perl 5, and I think it works quite well. I like having "custom" error-handling that fits the style and the purpose of that particular program, instead of trying to to fit a general pattern onto all programs. It also means you can start out with something very crude, and improve it as you go along and learn more about the failure modes etc.
It works fine in big programs, too. If you need more context, you add custom errors that have a context field. If you need to match different types of errors, you can have an error code that you can check against, or you can simply match strings (a lot of Go code does this). What you see as a problem is not really much of a problem in practice for well-structured code.
I don't really have an answer to that. But what i know is that i find the practice of having typed exception in java plus catching the one you want to deal with per block of code much more readable than the serie of if / else that go forces you to do.
Ps : i do write in many different languages, including C and python. But with C you know that you're writing in an prehistoric language so nothing cumbersome really surprises you, and python also has try / catch logic.
With Python, you just wrap it in a try/catch and forget about it. With Go, I already wrote five error checks and I'm sure I haven't caught some condition that will make it crash. I have to say I prefer the exception style, at least in this case.
if err != nil {
continue
}