设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 重新 试卷 创业者
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

一文悟透备受争议的 Go 语言错误处理(4)

发布时间:2019-09-19 12:45 所属栏目:21 来源:佚名
导读:当在外层调用 ReadFile 函数时: funcmain(){ _,err:=ReadConfig() iferr!=nil{ fmt.Println(err) os.Exit(1) } } funcReadConfig()([]byte,error){ home:=os.Getenv(HOME) config,err:=ReadFile(filepath.Join(hom

当在外层调用 ReadFile 函数时:

  1. func main() { 
  2.     _, err := ReadConfig() 
  3.     if err != nil { 
  4.         fmt.Println(err) 
  5.         os.Exit(1) 
  6.     } 
  7. func ReadConfig() ([]byte, error) { 
  8.     home := os.Getenv("HOME") 
  9.     config, err := ReadFile(filepath.Join(home, ".settings.xml")) 
  10.     return config, errors.Wrap(err, "could not read config") 

这样我们在 main 函数里就能打印出这样一个错误信息:

  1. could not read config: open failed: open /Users/dfc/.settings.xml: no such file or directory 

它是有层次的,非常清晰。而如果我们用 pkg/errors 库提供的打印函数:

  1. func main() { 
  2.     _, err := ReadConfig() 
  3.     if err != nil { 
  4.         errors.Print(err) 
  5.         os.Exit(1) 
  6.     } 

能得到更有层次、更详细的错误:

  1. readfile.go:27: could not read config 
  2. readfile.go:14: open failed 
  3. open /Users/dfc/.settings.xml: no such file or directory 

上面讲的是 Wrap 函数,接下来看一下 “Cause” 函数,以前面提到的 temporary 接口为例:

  1. type temporary interface { 
  2.     Temporary() bool 
  3. // IsTemporary returns true if err is temporary. 
  4. func IsTemporary(err error) bool { 
  5.     te, ok := errors.Cause(err).(temporary) 
  6.     return ok && te.Temporary() 

判断之前先使用 Cause 取出错误,做断言,最后,递归地调用 Temporary 函数。如果错误没实现 temporary 接口,就会断言失败,返回 false。

Only handle errors once

什么叫“处理”错误:

  1. Handling an error means inspecting the error value, and making a decision. 

意思是查看了一下错误,并且做出一个决定。

例如,如果不做任何决定,相当于忽略了错误:

  1. func Write(w io.Writer, buf []byte) { w.Write(buf) 
  2.     w.Write(buf) 

w.Write(buf) 会返回两个结果,一个表示写成功的字节数,一个是 error,上面的例子中没有对这两个返回值做任何处理。

下面这个例子却又处理了两次错误:

  1. func Write(w io.Writer, buf []byte) error {  
  2.     _, err := w.Write(buf) 
  3.     if err != nil { 
  4.         // annotated error goes to log file 
  5.         log.Println("unable to write:", err) 
  6.      
  7.         // unannotated error returned to caller return err 
  8.         return err 
  9.     } 
  10.     return nil 

第一次处理是将错误写进了日志,第二次处理则是将错误返回给上层调用者。而调用者也可能将错误写进日志或是继续返回给上层。

这样一来,日志文件中会有很多重复的错误描述,并且在最上层调用者(如 main 函数)看来,它拿到的错误却还是最底层函数返回的 error,没有任何上下文信息。

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读