V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
1000copy
V2EX  ›  问与答

一直不太明白, golang 不用 try catch 做错误处理,而使用 if err 这样的古老模式,其中有何深意吗?

  •  
  •   1000copy · 2015-09-11 12:56:33 +08:00 · 6279 次点击
    这是一个创建于 3379 天前的主题,其中的信息可能已经有所发展或是发生改变。
    第 1 条附言  ·  2015-09-11 13:55:38 +08:00
    提醒自己,即使不用 c++,也得学,不然很多东西懂不起。 http://dave.cheney.net/2012/01/18/why-go-gets-exceptions-right
    10 条回复    2015-09-14 00:06:05 +08:00
    gaitana
        1
    gaitana  
       2015-09-11 13:02:52 +08:00
    玩的就是与众不同
    songco
        2
    songco  
       2015-09-11 13:06:12 +08:00
    Why does Go not have exceptions?

    We believe that coupling exceptions to a control structure, as in the try-catch-finally idiom, results in convoluted code. It also tends to encourage programmers to label too many ordinary errors, such as failing to open a file, as exceptional.

    Go takes a different approach. For plain error handling, Go's multi-value returns make it easy to report an error without overloading the return value. A canonical error type, coupled with Go's other features, makes error handling pleasant but quite different from that in other languages.

    Go also has a couple of built-in functions to signal and recover from truly exceptional conditions. The recovery mechanism is executed only as part of a function's state being torn down after an error, which is sufficient to handle catastrophe but requires no extra control structures and, when used well, can result in clean error-handling code.

    See the Defer, Panic, and Recover article for details.
    nbndco
        3
    nbndco  
       2015-09-11 13:08:04 +08:00
    考虑到 go 是一个毫无设计的,虽然刚刚推出但本质上就是个八十年代的语言,你说他使用古老模式倒是也没啥特别的。
    不过返回错误值的方式其实是非常好的方式啊, rust 也是采用这种方式, haskell 也类似,只不过那个都做的比 go 不知道高到哪里去了。
    这个问题其实已经反反复复有过讨论了,一搜就是一大堆,连 go 自己都解释了 https://golang.org/doc/faq#exceptions
    YuJianrong
        4
    YuJianrong  
       2015-09-11 13:33:41 +08:00
    首先要搞清楚 go 其实是一个增强版的 C ,把 C 不太好的地方(比如内存管理)增强了一下,所以 C 里没有 try/catch go 里也没有也合理。
    其次我也是非常反对 try/catch 的, try/catch 本质上是一种跨函数的 goto (在 C 里可以用 setjmp/longjmp 模拟),连函数内的 goto 都深恶痛绝的现代程序开发怎么能接受一种能彻底改变程序流程的存在呢?所有的错误都应该正确地处理,而不是抛一个异常了事,滥用异常只会使得程序流程完全不可控。
    gonghao
        5
    gonghao  
       2015-09-11 13:34:26 +08:00
    Swift 2.0 已经学乖了,开始去除古老的 if err 模式,全部换成 try catch 了
    jadecoder
        6
    jadecoder  
       2015-09-11 14:08:46 +08:00
    @YuJianrong 虽然 try/catch 是一种 goto ,但是应用场景和 goto 并不一样,如果有人用 throw/catch 做跳转,那才是 [彻底改变程序流程] 。如果用来做异常处理,我觉得会让程序变得更清晰简洁
    linnchord
        7
    linnchord  
       2015-09-11 14:11:15 +08:00 via Smartisan T1
    try catch 是主动处理,可处理可不处理,极端的情况 web 开发中你可以不处理任何异常,直到最外层抛出,再统一记个日志完事。

    go 或者很多以面向系统层面开发的语言就是想极力避免这种情况,所以开启这种强迫模式,每调一次都会提醒你,处理错误,处理错误,处理错误…

    所以如果不是有极度性能要求,还是不要以这种系统级语言来开发 web ,这种琐碎带来的安全性对于一般应用层面来说性价比太低。
    sakeven
        8
    sakeven  
       2015-09-11 15:05:23 +08:00
    try catch 是异常处理
    if err 是错误处理。
    golang 的异常处理有 defer recover ()之类
    YuJianrong
        9
    YuJianrong  
       2015-09-11 15:35:08 +08:00
    @jadecoder 问题在于如何定义何为“异常”。异常可大可小,磁盘损坏读文件读不出来是系统级异常,某个函数参数应该小于 10 结果给了 11 是“业务异常”,然而很多做业务的时候就在最外面捕捉一下抛给前台了事,这能一样吗?
    滥用 try/catch 的结果就是根本不知道怎么就跑到异常处理去了,程序是简洁了,不过却让最终结果十分不可预测。
    所以既然说 try/catch 是 goto, 然而 goto 就是 goto ,虽然你小心地用 goto 也没啥问题(我就在很久以前的一个项目中用 setjmp/longjmp 来做异常恢复),但它本身存在就会有导致滥用的可能性,其带来的好处和带来的问题相比我觉得并不值得。
    reus
        10
    reus  
       2015-09-14 00:06:05 +08:00
    不是一定要用 if err != nil 来处理错误的,看这里: https://github.com/reusee/codes/tree/master/err
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   902 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 22:23 · PVG 06:23 · LAX 14:23 · JFK 17:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.