I don't know why so often, the immediate reaction to legitimate criticism of this wart in Go is to argue against exceptions, even when nobody has even brought up exceptions as an alternative.
In fact, Either/Maybe can function like safer versions of both paradigms: Functors allow you to build a program of many functions that will terminate with 'Nothing' or 'Either l' as long as any one of them experiences an error, without thinking about errors, and it still lets you explicitly handle any errors if you want to, this time on the sum type Maybe or Either, meaning that you usually handle both the error and non-error case, or receive a compiler warning.
I agree that, probably universally, the people who fervently argue for either exceptions or explicit Go-style error handling don't know about Maybe/Either/Result. Then again, all this is pretty much impossible to replicate in Go.
Thank you for mentioning this. It's frustrating that every time someone complains about Go's error-handling style, the first assumption is that the complainer then necessarily has to prefer exceptions. In truth, errors-as-values are very elegant in languages like Haskell IMO. And errors-as-values are not at all something that Go has managed to put back on the roadmap in a modern language against the grain of everyone else (the "exception people") as many seem to imply, including Rob Pike in his "errors as values" article.
Option types are nice. The fourth way (and I think the best) is supervision trees, though this is more applicable when you have multiple units of execution... which Go does, so not having something similar out of the box seems strange.
That said, even something as simple as errors being literal values that you can pattern match on is surprisingly versatile. Exceptions don't necessarily have to be awful weights that spill down all over the call stack, either. They can be distilled to a more basic catch/throw mechanism for shuffling around error properties and states.
Personally I love option types but working on a large Scala project at the moment it sometimes results in non ideal behaviour from developers especially those coming from the Java world.
What I've seen a lot of is swallowing of errors. For example readFromFile().orElse("") where there is no indication from an outsider that anything wrong happened. A cool feature would be logging any instance of when orElse was the result.
Would be curious how these work in other languages.
The trick is to make it very ergonomic to return the error. I thought Scala had do notation to make this the case. In Rust, the try! macro (which returns on error) is shorter than almost any other way to handle an error, so people usually use that.
I don't know why so often, the immediate reaction to legitimate criticism of this wart in Go is to argue against exceptions, even when nobody has even brought up exceptions as an alternative.