# 14.6 协程和recover

一个用到`recover`的程序（参见章节13.3）停掉了服务器内部一个失败的协程而不影响其他协程的工作。
```go 
func server(workChan <-chan *Work) {
    for work := range workChan {
        go safelyDo(work)   // start the goroutine for that work
    }
}

func safelyDo(work *Work) {
    defer func {
        if err := recover(); err != nil {
            log.Printf("Work failed with %s in %v", err, work)
        }
    }()
    do(work)
}
```
上边的代码，如果`do(work)`发生panic，错误会被记录且协程会退出并释放，而其他协程不受影响。

因为`recover`总是返回`nil`，除非直接在`defer`修饰的函数中调用，`defer`修饰的代码可以调用那些自身可以使用`panic`和`recover`避免失败的库例程（库函数）。举例，`safelyDo()`中`deffer`修饰的函数可能在调用`recover`之前就调用了一个`logging`函数，`panicking`状态不会影响`logging`代码的运行。因为加入了恢复模式，函数`do`（以及它调用的任何东西）可以通过调用`panic`来摆脱不好的情况。但是恢复是在`panicking`的协程内部的：不能被另外一个协程恢复。更多深入的细节处理可以在[http://www.tideland.biz/SupervisingGoroutines](http://www.tideland.biz/SupervisingGoroutines)（ref.43）找到。


## 链接

- [目录](directory.md)
- 上一节：[通道，超时和计时器](14.5.md)
- 下一节：[对比新旧模型：任务和工作](14.7.md)
