go · level 3 · unit 1 · lesson 4
- meet it
- guess first
- your turn
- fix it
- 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.
guess first
main has a recover. Does it save the day?
Guess before you run it. Wrong guesses are how you learn, and nothing is marked.
package main
import (
"fmt"
"sync"
)
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("main caught it")
}
}()
var wg sync.WaitGroup
wg.Add(1)
go func() {
var scores []int
fmt.Println(scores[3])
wg.Done()
}()
wg.Wait()
fmt.Println("all done")
}
your turn
Your turn. Catch the panic inside the job.
One pet has no name, so name[:1] panics. Fill in the call that catches the panic, then choose what the slot shows instead, such as ?.
output
press run to see what happens
fix it
The rescue will not even start. Can you fix it?
output
press run to see what happens
- Read the error. The deferred function has no return values of its own, so it cannot
returnone. - A deferred function changes the answer by setting a named result, like
resultin the lesson. - Change line 6 to
func share(sweets, kids int) (result string) {and line 9 toresult = "none".
nailed it
one bad job no longer sinks the rest. :D
- An unrecovered panic in any goroutine stops the whole program.
recoveronly works inside the goroutine that panicked.- A deferred
recoverplus a named result keeps the blast radius small.
new words in your collection
- blast radius
- named result
This lesson isn’t saved. A free account remembers every lesson you finish.