13.5 一种用闭包处理错误的模式

    假设所有的函数都有这样的签名:

    参数的数量和类型是不相关的。

    我们给这个类型一个名字:

    在我们的模式中使用了两个帮助函数:

    1)check:这是用来检查是否有错误和 panic 发生的函数:

    1. func check(err error) { if err != nil { panic(err) } }

    当错误发生时会 recover 并打印在日志中;除了简单的打印,应用也可以用 template 包(参见 )为用户生成自定义的输出。check() 函数会在所有的被调函数中调用,像这样:

    1. func f1(a type1, b type2) {
    2. ...
    3. f, _, err := // call function/method
    4. check(err)
    5. t, err := // call function/method
    6. check(err2)
    7. ...
    8. }

    通过这种机制,所有的错误都会被 recover,并且调用函数后的错误检查代码也被简化为调用 check(err) 即可。在这种模式下,不同的错误处理必须对应不同的函数类型;它们(错误处理)可能被隐藏在错误处理包内部。可选的更加通用的方式是用一个空接口类型的切片作为参数和返回值。

    我们会在 15.5 节的 web 应用中使用这种模式。

    练习

    练习 13.1

    练习 13.2panic_defer.go

    阅读下面的完整程序。不要执行它,写出程序的输出结果。然后编译执行并验证你的预想。

    输出:

    1. Calling g.
    2. Printing in g 0
    3. Printing in g 1
    4. Printing in g 2
    5. Panicking!
    6. Defer in g 3
    7. Defer in g 2
    8. Defer in g 1
    9. Defer in g 0
    10. Recovered in f 4
    11. Returned normally from f.

    练习 13.3

    写一个 ConvertInt64ToInt 函数把 int64 值转换为 int 值,如果发生错误(提示:参见 4.5.2.1 节)就 panic。然后在函数 IntFromInt64 中调用这个函数并 recover,返回一个整数和一个错误。请测试这个函数!