| 当在外层调用 ReadFile 函数时: func main() {     _, err := ReadConfig()     if err != nil {         fmt.Println(err)         os.Exit(1)     } } func ReadConfig() ([]byte, error) {     home := os.Getenv("HOME")     config, err := ReadFile(filepath.Join(home, ".settings.xml"))     return config, errors.Wrap(err, "could not read config") } 
 这样我们在 main 函数里就能打印出这样一个错误信息: could not read config: open failed: open /Users/dfc/.settings.xml: no such file or directory 
 它是有层次的,非常清晰。而如果我们用 pkg/errors 库提供的打印函数: func main() {     _, err := ReadConfig()     if err != nil {         errors.Print(err)         os.Exit(1)     } } 
 能得到更有层次、更详细的错误: readfile.go:27: could not read config readfile.go:14: open failed open /Users/dfc/.settings.xml: no such file or directory 
 上面讲的是 Wrap 函数,接下来看一下 “Cause” 函数,以前面提到的 temporary 接口为例: type temporary interface {     Temporary() bool } // IsTemporary returns true if err is temporary. func IsTemporary(err error) bool {     te, ok := errors.Cause(err).(temporary)     return ok && te.Temporary() } 
 判断之前先使用 Cause 取出错误,做断言,最后,递归地调用 Temporary 函数。如果错误没实现 temporary 接口,就会断言失败,返回  false。 Only handle errors once 什么叫“处理”错误: Handling an error means inspecting the error value, and making a decision. 
 意思是查看了一下错误,并且做出一个决定。 例如,如果不做任何决定,相当于忽略了错误: func Write(w io.Writer, buf []byte) { w.Write(buf)     w.Write(buf) } 
 w.Write(buf) 会返回两个结果,一个表示写成功的字节数,一个是 error,上面的例子中没有对这两个返回值做任何处理。 下面这个例子却又处理了两次错误: func Write(w io.Writer, buf []byte) error {      _, err := w.Write(buf)     if err != nil {         // annotated error goes to log file         log.Println("unable to write:", err)              // unannotated error returned to caller return err         return err     }     return nil } 
 第一次处理是将错误写进了日志,第二次处理则是将错误返回给上层调用者。而调用者也可能将错误写进日志或是继续返回给上层。 这样一来,日志文件中会有很多重复的错误描述,并且在最上层调用者(如 main 函数)看来,它拿到的错误却还是最底层函数返回的  error,没有任何上下文信息。 (编辑:宣城站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |