Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is a recovered panic always of type error?

I would like to return any panic as an error value in a function. Is it safe to assume that all panics are of type error (Example A) or do I need to tread them as strings (Example B) or something else?

Example A: Assuming panics are errors

func API() (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = r.(error)
        }
    }()
    mayPanic()
    return
}

Example B: Treating panics as strings

func API2() (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("%s", r)
        }
    }()
    mayPanic()
    return
}

In my tests both examples create the same output for panics, but there may be cases I am missing.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

No. It’s the type of whatever argument was supplied to the panic call that you are now recovering. In fact, the return value of recover is the same value supplied to panic.

Go specs: https://go.dev/ref/spec#Handling_panics

When the running of deferred functions reaches D [a function D that calls recover], the return value of D’s call to recover will be the value passed to the call of panic.

You can’t assume that all recovered values are errors, unless you are in full control of your code and somehow enforce passing errors to panic calls.

If the code you’re dealing with could pass arbitrarily typed values to panic, you should test for its type when recovering it:

func API() (err error) {
    defer func() {
        if r := recover(); r != nil {
            if err2, ok := r.(error); ok {
                err = err2 // or some other error wrapping
            } else {
                err = fmt.Errorf("recovered panic: %v", r)
            }
        }
    }()
    mayPanic()
    return
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading