标签:== 流程 通过 scratch grep 部分 head nil 中断
本文只是简单的介绍了五种错误处理策略,对于如何更优雅的处理错误,可以翻看我往期的文章。
go之父谈error
go 1.13的错误处理
传播错误
这意味着函数中某个子程序的失败,会变成该函数的失败。把流程中某个子函数的错误“传播”给主流程函数,并中断。
res, err := subFunc(arg)
if err != nil{
return nil, err
}
这样的错误返回也可以包装下
if err != nil {
return nil, fmt.Errorf(" %s : %v", arg,err)
}
可以额外了解下 go 1.14的 unwarp error 和 %w 占位符。这样使用传播错误可以使错误信息模拟调用过程,呈链式。当错误最终由main函数处理时,错误信息应提供清晰的从原因到后果的因果链。由于错误信息经常是以链式组合在一起的,所以错误信息中应避免大写和换行符。最终的错误信息可能很长,我们可以通过类似grep的工具处理错误信息(译者注:grep是一种文本搜索工具)。
重试
如果错误的发生时偶然性的(类似TCP的部分错误处理),那么我们可以采用重试的策略,但是要注意重试的时间和次数,防止无限制的重试。在所有重试之后如果还是失败的话,再返回错误。
// WaitForServer 尝试连接url参数对应的服务器
// 它持续一分钟的重连,并采用指数级的等待时间增加
// 如果所有重试都失败了,将返回错误
func WaitForServer(url string) error {
const timeout = 1 * time.Minute
deadline := time.Now().Add(timeout)
for tries := 0; time.Now().Before(deadline); tries++ {
_, err := http.Head(url)
if err == nil {
return nil // success
}
log.Printf("server not responding (%s);retrying…", err)
time.Sleep(time.Second << uint(tries)) // 指数递增
}
return fmt.Errorf("server %s failed to respond after %s", url, timeout)
}
第一时间结束
这个策略一般用在 main 文件中,当主流程遇到错误时,直接退出结束程序。
这个策略一般与 错误传播 策略合用,将子函数传播至主流程中,然后依照错误的严重性判断是否结束程序。
// 在主程序中
if err := WaitForServer(url); err != nil {
log.Fatalf("wrong %v\n",err)
os.Exit(1)
}
只输出错误信息,不中断
就是调用日志系统,常见于一些小问题,如图片丢失等。
忽略错误
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会失败,但上面的例子并没有做错误处理。这是因为操作系统会定期的清理临时目录。正因如此,虽然程序没有处理错误,但程序的逻辑不会因此受到影响。我们应该在每次函数调用后,都养成考虑错误处理的习惯,当你决定忽略某个错误时,你应该清晰地写下你的意图。
标签:== 流程 通过 scratch grep 部分 head nil 中断
原文地址:https://www.cnblogs.com/Jun10ng/p/12787865.html