What happens when a deferred function panics while the goroutine is already panicking?
Question 328HardGo 1.22 to 1.25
func main() {
defer func() { fmt.Println("recovered:", recover()) }()
defer func() { panic("second") }()
panic("first")
}
Output: recovered: second. The new panic replaces the one in progress. Unwinding continues with the new value, and recover returns only the most recent panic value. The first value is lost to recover. If nothing recovers, the crash output lists the whole sequence:
panic: first
panic: second
goroutine 1 [running]:
...
Practical consequences: cleanup code in a defer (closing files, unlocking, flushing) should not panic, because it hides the original cause. A recovery handler that logs recover() sees only the last panic. If cleanup can fail, return or log that error rather than panicking. Also remember that a panic in a deferred call still runs the remaining deferred calls in LIFO order.
More on Error Handling & panics
- Q326Implement a wrapper error type that adds context and works with
errors.Is/As. What happens if you forgetUnwrap? - Q327What does this print? (Which side's
Ismethod gets called) - Q329What happens if the function passed to
sync.Once.Dopanics? How dosync.OnceFuncandsync.OnceValuediffer? - Q330What are the performance costs of errors,
deferandpanic/recoverin hot paths?