zoukankan      html  css  js  c++  java
  • Go语言 关于go error处理风格的一些讨论和个人观点(上)

    原创文章。转载请注明出处:server非业余研究-sunface

    近期看谷歌go group里面有非常多讨论go error处理风格的问题,颇有启示。如今跟大家分享一下。首先请看一个提问:

    Hi folks,


    When I look at a lot of go code, I see the following pattern:
    //当我看了很多go代码后,我发现了下面模式

    x, err := foo()
    if err != nil {
    return err
    }

    y, err := bar(x)
    if err != nil {
    return err
    }

    z, err := baz(y)
    if err != nil {
    return err
    }

    // do something w/ z

    return nil

    This is cool, but comes off as a bit verbose. I've been using the following as a replacement, which I think is a bit nicer:
    //上段代码非常cool,可是表现的有点冗余。我已经用下面一种error机制作为替代。我觉得我的更好

    var (
    x, y, z T
    err      error 

    x, err = foo()

    if err == nil {
    y, err = bar(x)
    }

    if err == nil {
    z, err = baz(y)
    }
     
    if err == nil { 
    // do something w/ z
    }

    return err 

     
    //出于好奇。请问有人用过我这样的风格然后有发现过缺点吗?或者这样的风格并不好?尽管我觉得非常好

    Just curious, has anyone else used this sort of thing and found a pitfall? Or perhaps has an opinion as to why it isn't actually nice?

    I think it's nice =].

    看了上面两种错误处理风格。大家应该已经看出了部分端倪:第一种是比較传统的error处理方式,另外一种是作者觉得比較创新的error处理方式。

    先不说第一种的优缺点,

    另外一种首先在开头设置了全部接收error的变量。然后后面的error处理方式是环环相扣,冗余度很之高。且直到最后才return,也就是说假设代码够长。那你得看完中间全部的处理过程。在这里你仅仅有读完了整段代码才知道foo()产生的错误究竟是怎么处理的。

    然后一个评论中提出了一种个人认为不错的风格:

      value,err :=  bar()

      if err != nil {

            goto handleError

      }

    .

    .

    .

    .

      handleError:

            return err

    在这样的风格中不须要去知道goto和label中间的代码。能够直接进行错误处理并返回,因此代码简洁、可读性强、性能高且冗余度低。

    另一个评论提出了一种非常特别的风格:

    if x, err := foo(); err != nil {
       return err
    } else if y, err := bar(x); err != nil {
       return err
    } else if z, err := baz(y); err != nil {
       return err
    } else {
       // do something w/ x,y,z

       return nil
    }

    这样的写法的代码比較简洁,return的地方一眼便可得知。

    以下这样的风格能够节省大量的if语句

    func checkErr( err error) {

         if  err != nil {

                        //deal error here

         }

    }

    func main() {

         ting,err := whatever()

         checkErr(err)

    }

    以下再说说我个人对提问中第二段代码的看法,主要有3点:

         1.在第二段代码中,全部的有意义的代码都是环环相扣,每个if和return都要记在脑袋里,详细能够看下这篇文章:代码的嵌套——各种状态的组合。在第一段代码中全部的错误处理都是在产生错误代码的以下,非常easy发现什么代码导致了某个错误。并且在那些if代码块之后。你不须要操心之前的x,y,z。由于它们都是合法的。可是在第二段代码中,永远不能知道x,y,z是否合法,每次都得继续验证前面的值。

         2.由于第二段代码的错误处理和返回方式(环环相扣),我们就无法得知error的详细位置,唯一能做的就是彻底放弃然后无奈的说一句“代码有BUG了”,仅此而已。

         3.每次你往第二段代码的函数添加新的代码的时候,都要放在一个if代码快中。相反在第一段代码中,就不须要,由于仅仅有错误处理在if中。其它的都在外部处理

    这里仅仅是一个简单的抛砖引玉。希望大家能发表下寻常项目中使用的错误处理机制,一起讨论。

  • 相关阅读:
    vc生产垃圾清理
    完整的.h宏定义
    vs 2017 boost 安装目录 非安装
    cdlinux
    TryEnterCriticalSection
    go get 升级所有
    delphi win7 and high path
    本机激活Qemu网络配置 之桥接 win 10 2019 LTSC
    archlinux alsa安装,音量设置和音量信息保存
    windows搭建gcc开发环境(msys2) objdump
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5152862.html
Copyright © 2011-2022 走看看