现在的位置: 首页 > 综合 > 正文

Go语言 关于go error处理风格的一些讨论和个人观点(下)

2015年08月21日 ⁄ 综合 ⁄ 共 2403字 ⁄ 字号 评论关闭

原创文章,转载请注明出处:服务器非业余研究-sunface

 

对于Go来说错误如何处理是非常关键和重要的,这里我总结了一些方法可以避免错误的错误处理机制(具体见关于go error处理风格的一些讨论和个人观点(上))

 

1.错误代码常用风格:

以下两个例子第一个例子明显好过第二个

f, err := os.Open(path)
if err != nil {
    // handle error
}
// do stuff

 

f, err := os.Open(path)
if err == nil {
    // do stuff
}
// handle error

 

2.自定义错误处理风格:

      首先定义错误接口:

            type Error string

            func (e Error) Error() string { return string(e) }

      然后用类型断言判断错误类型

      result, err := yourpackage.Foo()
      if ype, ok := err.(yourpackage.Error); ok {
             // use ype to handle error
      }

      分析文件,并输出错误信息:

      type OpenError struct {
             File  *File
             Error string
      }

     func (oe *OpenError) Error() string {
             // format error string here
     }

     func ParseFiles(files []*File) error {
           for _, f := range files {
                 err := f.parse()
                if err != nil {
                   return &OpenError{
                       File:  f,
                       Error: err.Error(),
                   }
               }
           }
     }

     这样就知道具体哪个文件在分析的时候失败了。

     有一点要特别注意:封装错误,因为当你封装错误的时候,原本的错误信息可能会丢失:

      var c net.Conn
      f, err := DownloadFile(c, path)
      switch e := err.(type) {
            case net.Error:
                   // 关闭连接         

                 c.Close()
                 return e
            case error:
                  // error != nil
                  return err

             default:
                 // err == nil的时候会执行这里

       }
       // do other things.

      如果在这段代码中你封装了net.Error,则这段代码不会再认为是net方面出错了,也就不会关闭连接,继续使用之前错误的连接。一个比较好的办法是:当使用外部接口的时候,不要封装它们产生的错误!!

3.错误就像状态一样:

     有的时候你会暂时不处理一个错误,可能因为想延后处理,也可能因为错误会很快再出现一次。

     对于第一种情况,bufio就是一个很好的例子,当bufio.Reader遇到一个错误的时候,它会持有那个错误直到缓存为空,才会处理这个错误。

     对于第二种情况,go/loader是一个很好的例子,当它被调用且发生错误的时候,会持有那个错误,因为很可能它会被用相当的参数再调用一次。

 

4.使用函数来避免重复

     如果某种错误在不断重复的出现,就可以使用函数来简化:

      func handleError(c net.Conn, err error) {
               // 进行错误后续处理
      }

      func DoStuff(c net.Conn) error {
              f, err := downloadFile(c, path)
              if err != nil {
                  handleError(c, err)
                  return err
              }
   
             f, err := doOtherThing(c)
             if err != nil {
                 handleError(c, err)
                 return err
             }
       }

      或者可以使用下面这种风格:

func handleError(c net.Conn, err error) {
            if err == nil {
                  return
            }  
    //错误后续处理

}

func DoStuff(c net.Conn) error {
    defer func() { handleError(c, err) }()
    f, err := downloadFile(c, path)
    if err != nil {
        return err
    }
   
    f, err := doOtherThing(c)
    if err != nil {
        return err
    }
}

 

抱歉!评论已关闭.