• 16.10 糟糕的错误处理
    • 16.10.1 不要使用布尔值:
    • 16.10.2 避免错误检测使代码变得混乱:

    16.10 糟糕的错误处理

    依附于第13章模式的描述和第17.1小节与第17.2.4小节的总结。

    16.10.1 不要使用布尔值:

    像下面代码一样,创建一个布尔型变量用于测试错误条件是多余的:

    1. var good bool
    2. // 测试一个错误,`good`被赋为`true`或者`false`
    3. if !good {
    4. return errors.New("things aren’t good")
    5. }

    立即检测一个错误:

    1. ... err1 := api.Func1()
    2. if err1 != nil { }

    16.10.2 避免错误检测使代码变得混乱:

    避免写出这样的代码:

    1. ... err1 := api.Func1()
    2. if err1 != nil {
    3. fmt.Println("err: " + err.Error())
    4. return
    5. }
    6. err2 := api.Func2()
    7. if err2 != nil {
    8. ...
    9. return
    10. }

    首先,包括在一个初始化的if语句中对函数的调用。但即使代码中到处都是以if语句的形式通知错误(通过打印错误信息)。通过这种方式,很难分辨什么是正常的程序逻辑,什么是错误检测或错误通知。还需注意的是,大部分代码都是致力于错误的检测。通常解决此问题的好办法是尽可能以闭包的形式封装你的错误检测,例如下面的代码:

    1. func httpRequestHandler(w http.ResponseWriter, req *http.Request) {
    2. err := func () error {
    3. if req.Method != "GET" {
    4. return errors.New("expected GET")
    5. }
    6. if input := parseInput(req); input != "command" {
    7. return errors.New("malformed command")
    8. }
    9. // 可以在此进行其他的错误检测
    10. } ()
    11. if err != nil {
    12. w.WriteHeader(400)
    13. io.WriteString(w, err)
    14. return
    15. }
    16. doSomething() ...

    这种方法可以很容易分辨出错误检测、错误通知和正常的程序逻辑(更详细的方式参考第13.5小节)。

    在开始阅读第17章前,先回答下列2个问题:

    • 问题 16.1:总结你能记住的所有关于,ok模式的情况。

    • 问题 16.2:总结你能记住的所有关于defer模式的情况。