Reputation: 2626
I know that the Go idiomatic way to handle errors is that it's treated as a value which is checked using an if statement to see if it's nil or not.
However, it soon gets tedious in a long function where you would need to do this if err!=nil{...}
in multiple places.
I am aware that error handling is one of the pain points in the Go community.
I was just thinking why can't we do something like this,
func Xyz(param1 map[string]interface{}, param2 context string) (return1 map[string]interface{}, err error)
{
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("error: %s\n", r)
}
}()
.....
.....
.....
// Code causes a panic
}
In your function have a deferred function call which makes use of recover so that if any panic occurs the call stack will start unwinding and the recover function will be invoked causing the program to not terminate, handle itself and return the error back to the caller.
Here is a Go Playground example, https://play.golang.org/p/-bG-xEfSO-Q
My question is what is the downside of this approach? Is there anything that we lose by this?
I understand that the recover function only works for the same goroutine. Let's assume that this is on the same goroutine.
Upvotes: 0
Views: 1007
Reputation: 79556
Can you? Yes.
This is in fact done in a few cases, even in the standard library. See encoding/json for examples.
But this should only ever be done within the confines of your private API. That is to say, you should not write an API, whose exposed behavior includes a possible panic-as-error-state. So ensure that you recover all panics, and convert them to errors (or otherwise handle them) before returning a value to the consumer of your API.
What is the downside of this approach? Is there anything that we lose by this?
A few things come to mind:
error
type), do your inspection/action, then possibly re-panic. It's much simpler to do all this with just a simple error
value.panic
is a very blunt instrument in this regard, so you lose a lot of control.panic
+ recover
does not perform as well as simply returning an error. In situations where an error truly is exceptional, this may not matter (i.e. in the encoding/json
example, it's used when a write fails, which will abort the entire operation, so being efficient is not of high importance).I'm sure there are other reasons people can come up with. Google is full of blog posts on the topic. For your continued reading, here's one random example.
Upvotes: 2