The whole point is that exception handling code, when written robustly, looks almost like Go error handling code. That or you need to write a TON of magic cleanup classes which take a lot of time, are even more error prone, and less flexible than boring error handling code.
f, err := os.Open(filename)
if err != nil {
return fmt.Errorf("failed to open config file: %s", err)
}
// happy path
compare to:
File f;
try {
f = File.Open(filename)
}
catch (Exception e) {
throw new Exception(String.Format("failed to open config file: %s", e.Message))
}
// happy path
So, either you write code that looks like this, which is just like the Go code, or you don't, and you're handling your errors in a poor fashion.
What most people do, is they would let this function throw FileNotFoundException, and not catch it. There's at least three problems with that:
1. It leaks your implementation, so if later you're saving to memcache, you'll throw some different error, which could break consumers that have written code to handle the FileNotFoundException
2. It lacks context: file not found: foo.yaml ... wtf is foo.yaml and why was this random function trying to open it?
3. You can't tell programmatically what failed. Something threw a filenotfound... but you don't know if it was opening the config file or some other function, so you can't handle it properly.
There's also the fact that now anyone who calls your function needs to wrap it in a try/catch, or let an exception from 2 levels deep bubble up. So you can get FileNotFound: foo.yaml from your Initiate() function, and no one knows what that means.
That's what I mean by "almost no one [handles exceptions] correctly".