Go 的错误处理策略笔记

Go的错误处理是采用一个内置的 error 接口来处理:

 // The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
    Error() string
}

error类型的值可能是 nil 或者 non-nil 。nil 意味着函数运行成功,non-nil 表示失败。对于non-nil 的error类型,我们可以通过调用 error 的 Error() 函数或者输出函数获得字符串类型的错误信息。
如下面代码输出即可:

fmt.Println(err.Error())
fmt.Printf("%v", err)

错误处理策略
* 1.传播错误 *
意味着函数中某个子程序的失败,会变成该函数的失败。

resp, err := http.Get(url)
if err != nil {
return nill, err
}

2.重新尝试失败的操作
错误的发生是偶然性的,或由不可预知的问题导致的。一个明智的选择是重新尝试失败的操作。在重试时,我们需要限制重试的时间间隔或重试的次数,防止无限次重试。

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"
)

func waitForServer(url string) error {
    const timeout = 1 * time.Minute
    deadline := time.Now().Add(timeout)

    for tries := 1; time.Now().Before(deadline); tries += 1 {
        _, err := http.Get(url)
        if err == nil {
            return nil
        }

        log.Printf("Server not respond (%v);the %d times retry....", err, tries)
        time.Sleep(time.Second * 2)
    }
    return fmt.Errorf("server %v failed to respond,after %s", url, deadline)
}
func main() {
    url := "http://xxxx.com"
    fmt.Println(waitForServer(url))
}

* 3.输出错误信息并结束程序*
如果错误发生后,程序无法继续运行。我们就可以输出错误并结束程序。需要注意的是,这种策略只应在 main 中执行。

// (In function main.)
if err := WaitForServer(url); err != nil {
    fmt.Fprintf(os.Stderr, "Site is down: %v\n", err)
    os.Exit(1)
     }
    ```
  *** 4.输出错误信息不需要中断程序的运行***
这个可以通过 log 包提供的函数实现。
```go
if err := Ping(); err != nil {
    log.Printf("ping failed: %v; networking disabled",err)
    }

或者

if err := Ping(); err != nil {
    fmt.Fprintf(os.Stderr, "ping failed: %v; networking disabled\n", err)
        }

* 5.直接忽略掉错误*
go dir, err := ioutil.TempDir("", "scratch") if err != nil { return fmt.Errorf("failed to create temp dir: %v",err) } // ...use temp dir... os.RemoveAll(dir) // ignore errors; $TMPDIR is cleaned periodically
上面的代码尽管 os.RemoveAll 会失败,但上面的例子并没有做错误处理。这是因为操作系统会定期的清理临时目录。正因如此,虽然程序没有处理错误,但程序的逻辑不会因此受到影响。

  • 我们应该在每次函数调用后,都养成考虑错误处理的习惯,当你决定忽略某个错误时,你应该在清晰的记录下你的意图*

总结:在Go中,错误处理有一套独特的编码风格。检查某个子函数是否失败后,我们通常将处理失败的逻辑代码放在处理成功的代码之前。如果某个错误会导致函数返回,那么成功时的逻辑代码不应放在else语句块中,而应直接放在函数体中。Go中大部分函数的代码结构几乎相同,首先是一系列的初始检查,防止错误发生,之后是函数的实际逻辑。

本作品采用《CC 协议》,转载必须注明作者和本文链接
不卑不亢,不慌不忙,这才是生活的模样。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!