It looks like it's not possible to recover from a panic inside a panic?
func TestError(t *testing.T) {
e := &myErr{p: false}
fmt.Println(e.Error()) // this prints "returned"
panic(e) // this prints "panic: returned"
e1 := &myErr{p: true}
fmt.Println(e1.Error()) // this prints "recovered"
panic(e1) // this prints "panic: panic: paniced
// fatal error: panic holding locks
// panic during panic"
}
type myErr struct {
p bool
}
func (m *myErr) Error() (out string) {
defer func() {
if r := recover(); r != nil {
out = "recovered"
}
}()
if m.p {
panic("paniced")
}
return "returned"
}
Backstory: My error Error() function uses os.Getwd, which seems to always panic when inside a panic, so I'd like to handle this gracefully.
I think it solves your problem to replace this
panic(e1)
by this
panic(e1.Error())
Playground: http://play.golang.org/p/fXpX2ch9eF
And the question here is interesting: why? This is the hard part and I don't know the exact answer. Probably the problem here is that we panicing after all deffered functions executed (so when Go does try to print the panic error string). Any correction is welcomed if it's not correct!