panic and recover
You met the rule of thumb back in the functions/errors lessons: expected failures return an error; panic is for what should never happen. panic immediately stops normal execution, running any deferred calls on the way up, then crashes the program — unless something calls recover.
func safeDivide(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered from panic: %v", r)
}
}()
return a / b, nil // dividing by zero panics
}recover() only does anything inside a deferred function, and only stops a panic that's actively unwinding — calling it in ordinary code does nothing. This pattern (defer a function that calls recover, and turn the panic into a regular error) is how a long-running program — a web server handling one request among thousands — survives an unexpected panic in one request-handling goroutine without taking the whole process down. It's the exception, not the rule: most Go code never calls recover, because most Go code is careful to make sure it never panics in the first place. That instinct — push failure handling into an explicit, checked return value rather than an escape hatch you reach for at the last second — is the thread running through everything in this course.