> It gets returned to the next level up, exactly like in the analogous Go code above.That sounds utterly horrible. You would never actually write that Go code in the real world.
Let's modify the original example slightly:
res1, err1 = canFailA()
if err1 != nil {
return err1
}
res2, err2 = canFailB()
if err2 != nil {
return err2
}
Let's assume an error was returned. You realize from the error that there is a bug in the code. Now you're tasked with debugging the code given the error that was presented.
Which function did the error come from? Who knows. And what if canFailA/canFailB return errors from other functions up the stack the same way? Now you've got a massive tree of possibilities to try and work through. A complete nightmare.
In the real world you would take the error and do something with it. Even if you still end up returning an error, it won't be the error you received. It will be a new error that provides pertinent information about the situation.
Go brought forth a legitimate "try" proposal that was very similar to the Rust example and, while well received on the surface, it failed because it was determined that you couldn't possibly use it, at least not beyond toy examples, because of the above.
Presumably Go could introduce a concept of error (it currently has none) which could then include information like stack traces to help with that problem, but that's way more than what you're talking about, and would still lack all the other benefits you get when you handle errors as soon as you get them, not blindly pass them up the stack.
Rust's solution may be nice for Rust, being designed for that pattern. It wouldn't fit well in Go without radically rethinking the language.
> On the other hand, Go will let you forget to handle an error, if you do "res1, err1 = canFail()" but then forget to return an error yourself in the "err1" case.
You can also forget to return res1 (per the original example).
This is a real problem that should be solved, but it's not a problem of errors. It's a problem of values in general. Remember, the Go language has no inherit concept of error. Anything that we happen to call an error is actually just a user-defined type, same as any other type a user might define (birthdate, order number, stock price, etc.).
To frame it as a problem of errors shows a misunderstanding of the problem.