4 ms·
> Frankly, I’ve seen as many golang error handling bugs in the wild as I ever did with java or c# style exceptions. This has not been my experience. Idiomatic
by sagichmal 9y ago
> Frankly, I’ve seen as many golang error handling bugs in the wild as I ever did with java or c# style exceptions.
This has not been my experience. Idiomatic Go -- that is, not trying to do obtuse, clever, or dumb things to avoid error handling -- results in very clean and error-free code by default. I see unexpected runtime errors maybe a few times a year. I haven't seen unexpected panics in years.
- kasey_junk 9y agoSerious question, when you see non obtuse, clever or dumb things for error handling how do you attribute language?
- sagichmal 9y agoAttribute language? I'm not sure what you mean. In Go there is typically a very restricted set of ways to idiomatically accomplish a given task, often only one. Error management is a prime example. result, err := function() What do you do with err? If it is recoverable, you should try to recover from it. if err == ErrTryAgain { continue } Generally errors aren't recoverable, and should be reported back up the stack with some kind of contextual annotation. if err != nil { return fmt.Errorf("function failed: %v", err) } If you want to provide more context to your caller, to enable a richer set of responses to this error, you can use more structure. if err != nil { return FunctionError{Original: err, ...} } That's really about it. Anything that tries to subvert the very simple/plain `if` checking, or tries to perform some kind of monadic error chaining, or builds an ersatz exception system with panic/recover, is what I mean when I talk about "obtuse, clever, or dumb things". The language and its idioms form these expectations.
- tptacek 9y agoThis is in fact not idiomatic Go style. The Go error idiom is that errors are values, and that if you want cleaner error abstractions, you just program them yourself. People make trees of errors, or aggregate errors and check them once, or have error stacks. "continue" doesn't recover from an error, obviously. It is not hard to find screwups in error recovery code in Go. Your "fmt.Errorf" "idiom" (it unfortunately really is one) is one of the major Go error handling warts. Since you (like everyone else) didn't create an error variable or type to capture any of the meaning of the error, what you've created is a by-design unrecoverable error, one where your only hope of responding in any way other than aborting the entire operation is to parse the string error message, which is something more than one Go program has had to do. I don't think this is a very strong rebuttal to "Go error handling kind of sucks".
- sagichmal 9y ago> This is in fact not idiomatic Go style. This is absolutely idiomatic, with progressively increasing levels of opt-in expressivity. "If you want [additional] error abstractions, you just program them yourself" was clearly demonstrated: my "tree" of error-chaining was only one level deep (FunctionError), but that's a nit. > "continue" doesn't recover from an error, obviously. ErrTryAgain clearly carries semantic meaning that "continue" acts upon. > Your "fmt.Errorf" "idiom" (it unfortunately really is one) is one of the major Go error handling warts. Since you (like everyone else) didn't create an error variable or type to capture any of the meaning of the error, what you've created is a by-design unrecoverable error, one where your only hope of responding in any way other than aborting the entire operation is to parse the string error message, which is something more than one Go program has had to do. I demonstrated an alternative for situations when clients might want to parse and act on errors.
- tptacek 9y agoAnd in doing that, you demonstrated that the idiomatic default in Go error handling is unhandleable errors, the sort that forces programmers to pitifully parse strings to differentiate. I kind of love Go. I'm a former professional C programmer and Go is now my default language. But I don't feel a need to kid people about things Go gets wrong.
- sagichmal 9y agoIf the user can do anything with the error, then it is idiomatic to return a discrete, comparable error variable var ErrTryAgain = errors.New("...") or an error type with additional contextual information type RetryError struct { ... } These are both opt-in; if your users have no need to differentiate or act on errors, fmt.Errorf("...") is totally sufficient. You're acting as if this is some critical flaw in the language. It's nothing like that.