> 1. Go's error handling has four possible cases (result and no error, no result and error, result and error, no result and no error) when only two make sense.
A partial success, that returns both a result and an error definitely makes sense. For example, you’re streaming data over a network, receive some bytes, but get disconnected before it’s complete. It would make sense to have both the data received so far as well as the error, in order to resume.
I’m sure there’s an appropriate situation for the 4th case as well.
This is why it's table stakes for a decent type-system to have both product-types and sum-types. They comprise both sides of the coin, and you use the one that actually makes sense for the piece of code being written.
A justification for Go's deficient type-system I've seen repeatedly over the years, along the lines of "Well actually the occasional function can legitimately return both a result AND an error" is nonsensical. It's basically excusing giving 98% of error-returning functions a semantically wrong return type (a tuple) because it happens to be correct in 2% of cases.
Every function should have a semantically correct return type! If a product-type is occasionally correct for an error-returning function, use one just for those functions! And use a sum-type for the other 98% where that is correct for them!
Exactly. One can think of examples where these cases make sense, but there are many more examples where there are more cases (e.g. there many be multiple kinds of partial successes) or fewer (most functions, which either succeed or fail.)
Also, the design requires null values. A point which the replies have ignored.
A partial success, that returns both a result and an error definitely makes sense. For example, you’re streaming data over a network, receive some bytes, but get disconnected before it’s complete. It would make sense to have both the data received so far as well as the error, in order to resume.
I’m sure there’s an appropriate situation for the 4th case as well.