问下go的错误处理风格选择 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
sillyousu
V2EX    Go 编程语言

问下go的错误处理风格选择

  •  
  •   sillyousu
    sillyousu 2013-08-21 17:26:25 +08:00 2957 次点击
    这是一个创建于 4435 天前的主题,其中的信息可能已经有所发展或是发生改变。
    if data, err := GetData(); err != nil {
    //handle error
    } else {
    //bz job
    }

    还是
    if data, err := GetData(); err == nil {
    //bz job
    } else {
    //handler error
    }

    我倾向与把错误处理卸载前面,应为错误现在的错误处理都比较短。

    问:
    1. 哪种是普适好选择(如果有的话)?为什么?
    2. 还是应该根据情景选择,考虑哪些因素?
    第 1 条附言    2015-06-25 19:40:06 +08:00
    现在我倾向于这么做:
    在框架设计时,严格区分业务逻辑和框架核心逻辑。
    业务逻辑特点是多变需要快速迭代;框架核心逻辑特点是一个字稳。

    在设计上,业务逻辑一个允许脑残写,并应该不被核心逻辑信任(类似内核和用户进程的关系)

    a) 业务逻辑代码应该设计上尽量不允许发生致命错误。
    以 a 为前提下,我们可以在业务逻辑中使用 panic 做错误处理。
    业务逻辑入口捕获业务逻辑产生的错误,并记录详细日志。

    核心逻辑则应该尽量少 隐瞒错误,应该认为正常情况下不会有任何错误。除非非常清楚吃掉的是什么错误(比如客户端连接 EOF 之类的)否则 宁愿 panic 让整个进程死掉。

    func some_bz() {
    PanicIf(db == nil, "err msg")
    }

    func gateway() {
    defer func() {
    if err := recover(); err != nil {
    switch err.(type) {
    case FatalError: panic(err)
    }
    log()
    }
    }
    some_bz()
    }
    14 条回复    1970-01-01 08:00:00 +08:00
    suchj
        1
    suchj  
       2013-08-21 17:37:12 +08:00   1
    我个人是这样做的,大部分函数都会带错误返回,因此:

    if data, err := GetData(); err != nil {
    //handle error
    return
    }

    假如不需要错误返回,仅需错误处理,也是上面这种方式,没必要带一个 else,接着写正常的处理流程就行了,这样可以减少代码的嵌套层数,使代码更加清晰:

    if data, err := GetData(); err != nil {
    //handle error
    }
    //blabla...

    具体可以参考 Go 编程语言的 12 条最佳实践:
    http://www.oschina.net/news/42825/go-best-practices?from=20130804
    reusFork
        2
    reusFork  
       2013-08-21 17:42:58 +08:00
    用第一种就不需要else了
    chisj
        3
    chisj  
       2013-08-21 18:01:29 +08:00
    异常处理一般都是写前面的,什么语言都一样。
    rwx
        4
    rwx  
       2013-08-21 18:10:55 +08:00   1
    先判断错误尽早返回
    另外像
    if data, err := GetData(); err != nil {
    //handle error
    return
    }
    这种形式data的作用域只是在if内部吧,后续完全没法利用到了
    除非需要判断err,否则我一般写成
    data, err := GetData()
    if err != nil {
    //handle error
    return
    }
    dosomething(data)
    rwx
        5
    rwx  
       2013-08-21 18:11:51 +08:00
    #4 「除非需要判断err」->「除非只需要判断err」
    sillyousu
        6
    sillyousu  
    OP
       2013-08-21 18:24:17 +08:00
    @reusFork
    这是公司的一个内部系统的代码。
    现在的代码对某些错误只做了log,没有返回

    其实我比较喜欢
    data, err := GetData()
    if err != nill {
    //handle err & return
    }
    //bz job
    这样写的。
    janxin
        7
    janxin  
       2013-08-21 18:54:22 +08:00
    data, err := GetData()
    if err != nill {
    //handle err & return
    }

    目前基本是这种方式,很多时候需要注意return,还好go里不用考虑释放什么的问题,否则弄不好就泄漏了

    if err == nill {
    ....
    }else{
    //handle err & return
    }
    很多时候做容错情况下用,就是有些情况这样用比较好
    RisingV
        8
    RisingV  
       2013-08-22 09:30:24 +08:00
    因为错误不是在所有地方都能进行处理的,等返回到可以处理的地方,你可能已经不知道错误是哪个地方来的。
    这是go的末尾返回error的弊端所在,try/catch方式就能记录完整的调用栈。但是go的这种简洁的方式,很多时候也够用了。
    作为弥补,可以自己写一套简单的库,在error返回时,封装更多的调用信息进去。这样排错的时候,可以节省很多功夫。
    fanweixiao
        9
    fanweixiao  
       2013-09-03 16:27:31 +08:00
    同意1楼意见。去掉嵌套后代码逻辑清晰直观,在panic起来也会方便很多,更适合使用goroutine去pipe各种业务了。有时候在 err != nil 的时候可能要写更多的业务。
    meta
        10
    meta  
       2013-09-07 12:59:56 +08:00
    if...else里面不能同时有return,所以最好不要写else。
    Syndim
        11
    Syndim  
       2013-09-07 14:25:49 +08:00   1
    @meta Go 1.1 可以了
    bombless
        12
    bombless  
       2013-09-07 17:13:16 +08:00
    就算try-catch可以找回抛出错误的调用栈,但同一个函数里你怎么知道返回的错误都是类似的?你还是要就地处理错误然后抛出另一个异常。就这一点来说go的风格也是类似的。

    再说了,一般人处理的时候根本不会去看是哪个栈抛出的错误。
    bombless
        13
    bombless  
       2013-09-07 17:13:55 +08:00
    我是说八楼的
    meta
        14
    meta  
       2013-09-07 18:40:32 +08:00
    @Syndim 是吗,感谢提醒,我都没太注意现在是1.1了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3480 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 00:17 PVG 08:17 LAX 17:17 JFK 20:17
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86