Go 的错误处理策略笔记
// 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 协议》,转载必须注明作者和本文链接