×

go · level 3 · unit 1 · lesson 4

  1. meet it
  2. guess first
  3. your turn
  4. fix it
  5. nailed it

Tap a green word if you get lost.

meet it

A panic in any goroutine brings down the whole program.

A panic that nobody recovers ends the whole program, not only the goroutine that panicked. One bad job takes every other job down with it. Worse, recover only works inside the goroutine where the panic happened: a recover in main cannot catch a panic in a goroutine main started.

So each job guards itself. Its function defers a small function that calls recover. Give the return value a name, like (result string), and that deferred function can overwrite it after a panic. A like this turns a crash into a message in that job's slot.

How much one failure can break is called its . Recovering inside each job shrinks the blast radius to that one job.

package main
import (
	"fmt"
	"sync"
)
func share(sweets, kids int) (result string) {
	defer func() {
		if r := recover(); r != nil {
			result = fmt.Sprint("failed: ", r)
		}
	}()
	return fmt.Sprint(sweets / kids)
}
func main() {
	kids := []int{4, 0, 5}
	answers := make([]string, len(kids))
	var wg sync.WaitGroup
	for i, k := range kids {
		wg.Add(1)
		go func(i, k int) { defer wg.Done(); answers[i] = share(20, k) }(i, k)
	}
	wg.Wait()
	fmt.Printf("%q\n", answers)
}

%q prints each string in quotes, so you can see exactly where one answer ends and the next begins.