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 · 2272 次点击
    这是一个创建于 3873 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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   ·   我们的愿景   ·   实用小工具   ·   5186 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 09:28 · PVG 17:28 · LAX 02:28 · JFK 05:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.