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

2015-09-11 12:56:33 +08:00
 1000copy
6165 次点击
所在节点    问与答
10 条回复
gaitana
2015-09-11 13:02:52 +08:00
玩的就是与众不同
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
2015-09-11 13:08:04 +08:00
考虑到 go 是一个毫无设计的,虽然刚刚推出但本质上就是个八十年代的语言,你说他使用古老模式倒是也没啥特别的。
不过返回错误值的方式其实是非常好的方式啊, rust 也是采用这种方式, haskell 也类似,只不过那个都做的比 go 不知道高到哪里去了。
这个问题其实已经反反复复有过讨论了,一搜就是一大堆,连 go 自己都解释了 https://golang.org/doc/faq#exceptions
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
2015-09-11 13:34:26 +08:00
Swift 2.0 已经学乖了,开始去除古老的 if err 模式,全部换成 try catch 了
jadecoder
2015-09-11 14:08:46 +08:00
@YuJianrong 虽然 try/catch 是一种 goto ,但是应用场景和 goto 并不一样,如果有人用 throw/catch 做跳转,那才是 [彻底改变程序流程] 。如果用来做异常处理,我觉得会让程序变得更清晰简洁
linnchord
2015-09-11 14:11:15 +08:00
try catch 是主动处理,可处理可不处理,极端的情况 web 开发中你可以不处理任何异常,直到最外层抛出,再统一记个日志完事。

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

所以如果不是有极度性能要求,还是不要以这种系统级语言来开发 web ,这种琐碎带来的安全性对于一般应用层面来说性价比太低。
sakeven
2015-09-11 15:05:23 +08:00
try catch 是异常处理
if err 是错误处理。
golang 的异常处理有 defer recover ()之类
YuJianrong
2015-09-11 15:35:08 +08:00
@jadecoder 问题在于如何定义何为“异常”。异常可大可小,磁盘损坏读文件读不出来是系统级异常,某个函数参数应该小于 10 结果给了 11 是“业务异常”,然而很多做业务的时候就在最外面捕捉一下抛给前台了事,这能一样吗?
滥用 try/catch 的结果就是根本不知道怎么就跑到异常处理去了,程序是简洁了,不过却让最终结果十分不可预测。
所以既然说 try/catch 是 goto, 然而 goto 就是 goto ,虽然你小心地用 goto 也没啥问题(我就在很久以前的一个项目中用 setjmp/longjmp 来做异常恢复),但它本身存在就会有导致滥用的可能性,其带来的好处和带来的问题相比我觉得并不值得。
reus
2015-09-14 00:06:05 +08:00
不是一定要用 if err != nil 来处理错误的,看这里: https://github.com/reusee/codes/tree/master/err

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/219918

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX