Error handling is hard. Checked exceptions and Go’s error returns are both good attempts to solve it. They both have plenty of drawbacks but they’re really different approaches here.
> This is precisely how checked exception handling works in Java, and yet there's no shortage of people complaining about it and praising how Go "makes you deal with it the way you're supposed to."
Just because people complain about Java’s checked exceptions does’t mean that their complaints are correct or that they somehow apply to Go’s errors.
The main complaints I hear about checked exceptions are that they force you to expose the types of all possible exceptions in the method signature. This creates unexpected API churn and design difficulties, because it’s difficult to predict which exception types you would want to expose from a particular interface.
You also have to choose which errors are programming errors and which are not when you declare the error type. This turned out to cause problems. NumberFormatException is an example.
> So do checked exceptions. And 99% of the time, the solution to an error popping up in Java is to blindly re-throw it because hey, I'm just a component buried a couple levels deep in a REST call, what could I possibly do to fix the problem?
In Go, blindly returning an error is done much less than 99% of the time, at least in the code bases I’ve worked on or read.