Go

What happens if a goroutine panics? Can the parent recover it?

Question 167MediumGo 1.22 to 1.25

A panic that no one recovers, in any goroutine, crashes the whole process and prints that goroutine's stack. recover works only inside a deferred function in the same goroutine that panicked. A parent cannot catch its child's panic:

func main() {
	defer func() { fmt.Println("recovered?", recover()) }() // never sees it
	go func() { panic("boom") }()
	time.Sleep(time.Second)
}
// Output: panic: boom ... exit status 2

A common pattern in servers is a safe-go wrapper that turns the panic into an error or a log entry:

func safeGo(wg *sync.WaitGroup, errs chan<- error, fn func()) {
	wg.Go(func() {
		defer func() {
			if r := recover(); r != nil {
				errs <- fmt.Errorf("panic: %v\n%s", r, debug.Stack())
			}
		}()
		fn()
	})
}

Gotchas:

  • net/http recovers panics in handlers, but not in goroutines the handlers start.
  • errgroup does not turn a panic into an error returned by Wait. Recover inside the function if you need that.
  • Fatal runtime errors, such as concurrent map writes, running out of memory, or stack overflow, cannot be recovered.

More on Goroutines & the Scheduler

All 35 Goroutines & the Scheduler questions