每当函数返回时,我们应该检查是否有错误发生:但是这会导致重复乏味的代码。结合 defer/panic/recover 机制和闭包可以得到一个我们马上要讨论的更加优雅的模式。不过这个模式只有当所有的函数都是同一种签名时可用,这样就有相当大的限制。一个很好的使用它的例子是 web 应用,所有的处理函数都是下面这样:
funchandler1(w http.ResponseWriter, r *http.Request) { ... }
假设所有的函数都有这样的签名:
funcf(a type1, b type2)
参数的数量和类型是不相关的。
我们给这个类型一个名字:
fType1 =funcf(a type1, b type2)
在我们的模式中使用了两个帮助函数:
1)check:这是用来检查是否有错误和 panic 发生的函数:
funccheck(err error) { if err !=nil { panic(err) } }
funcerrorHandler(fn fType1) fType1 {returnfunc(a type1, b type2) {deferfunc() {if err, ok :=recover().(error); ok { log.Printf("run time panic: %v", err) } }()fn(a, b) }}
// panic_defer.go
package main
import "fmt"
func main() {
f()
fmt.Println("Returned normally from f.")
}
func f() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
fmt.Println("Calling g.")
g(0)
fmt.Println("Returned normally from g.")
}
func g(i int) {
if i > 3 {
fmt.Println("Panicking!")
panic(fmt.Sprintf("%v", i))
}
defer fmt.Println("Defer in g", i)
fmt.Println("Printing in g", i)
g(i + 1)
}
Calling g.
Printing in g 0
Printing in g 1
Printing in g 2
Printing in g 3
Panicking!
Defer in g 3
Defer in g 2
Defer in g 1
Defer in g 0
Recovered in f 4
Returned normally from f.