4 ms·
Attribute 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
by sagichmal 9y ago
Attribute 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.