每当函数返回时,我们应该检查是否有错误发生:但是这会导致重复乏味的代码。结合 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.gopackagemainimport"fmt"funcmain() {f() fmt.Println("Returned normally from f.")}funcf() {deferfunc() {if r :=recover(); r !=nil { fmt.Println("Recovered in f", r) } }() fmt.Println("Calling g.")g(0) fmt.Println("Returned normally from g.")}funcg(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.