Golang Go语言社区否决了新的 try 语句提议

发布于 1周前 作者 songsunli 来自 Go语言

Golang Go语言社区否决了新的 try 语句提议

Proposal: A built-in Go error check function, “try” · Issue #32437 · golang/go https://github.com/golang/go/issues/32437

77 回复

更多关于Golang Go语言社区否决了新的 try 语句提议的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我也觉得,如果单纯是语法糖的话,旧语法和新语法间可以完全相互转换的话,没有必要。

刚好前几天看了眼,感觉 try 根本就没解决问题,只是看起来 /写起来稍微简单了点,所以被拒是正常的。

其实 try() 不是真正的 error handling,只是检查 err != nil 并直接返回,Griesemer 的 tryhard 工具也验证了在现有代码库里能应用到的地方很有限,为了这一点点便利而引入一种新的写法不值得。

我认为当前 if err != nil 的模式肯定有可以改进的地方,但肯定不是 try(),所以很高兴这个提案被撤回了。

这个好, 虽然 if err!=nil 是有点啰嗦,但是对于程序稳定性真的非常好

#2
#3

语法糖为什么没有必要。。。
async await 就是 Promise+Generator 的语法糖啊。。。
能节省开发效率当然是好事。。。

否决不是坏事,起码社区力量的展示吧。

要解决就一次性永久解决,别搞什么中间方案,支持否决。

非常 nice。
没有对写法造成根本性的改变的语法糖,我认为是不必要的。
相应的,js 的 async await 语法糖带来的是颠覆式的书写风格,利远大于弊,当然觉得很好,而 go 中的 try 不但没有根治异常处理,还带来了恶心的函数嵌套。
我理解的是 Go 社区不应该过分坚持简单、单一哲学,坚持没错,但是这个地方如此沉重,和泛型一样,应该有大刀阔斧的改革勇气

这个 try 函数作为语法糖的意义确实很低…… go 目前的关键字和内置函数很克制,个人认为加这样一个隐藏细节且对程序稳定性没有好处的谜之语法糖并没有使 go 的 error handle 更友好的效果。


async await 收益巨大,傻子也能写异步了。promise 真的太难了。
try 相比之下收益太小了,错误处理还是要写,只能包一个 func (这点真的很蠢……),而且现在很多 MustFunc 写法。总之看起来就不是个好的解决方案,况且它没解决根本问题。

try(try(try(try(try(try(try(try(try(try(f()))))))))))

你要是敢让人这么写,就一定会有人这么写。实际上我是支持解决 error hanling 问题,但是 built-in try 函数方案,就是不行…其实我倒是觉得引入 Rust 的?可以,不过大佬们觉得麻烦不是,我觉得这个事情社区可以再推一推

go 的事情 能和 ecmascript 一样么?

#12 只存在不用和滥用,不滥用是不可能的

try 这样的语法糖,第三方实现的很多了,喜欢的早用上了,算啥改进啊

rust 的也很麻烦的,match match match unwrap unwrap 顺带 Some 里面的内容可能是引用的,处理起来就是一个字,烦。

go 没有宏,怎么做语法糖?包个函数做法太奇怪了。

跟异常比起来,哪里对稳定性好?

有什么好 try 的
错误都不处理 还想写出来好软件

能用 promise 把异步写清楚的人也许十个里面只有两三个,能用 async-await 写清楚的可能就只有半个,来源于我面试下来的主观感受

https://github.com/manucorporat/try . 类似这样的,我随手搜了个,应该有更完善的

所以都要传 lambda 过去,很奇怪的。

感觉 "if err != nil " 问题不大, 并不是迫切的需求,泛型才是。

try 还是没解决 if err != nil 啰嗦的问题

好个毛线,标准库内部都偷偷 panic/recover 来当异常用。假如 err 这么好,为什么还用这种自己不推荐,内部偷偷用的玩意?

err 唯一不好用就是没有输出堆栈,return 什么的根本不是问题,代码扫描检查 error 有没有处理就很简单,只要正常处理基本不会崩溃

这个 try 是真丑

按理说 go 的程序和库都是基于源码的,不用考虑二进制兼容性,优化语言不算太麻烦的,还是那帮人太偏执。

支持!
不喜欢 try 写 if 更自由

喜欢 rust 的 err handling 方式

rust 的 match err 和 if err 有啥区别?还不是通过返回值

rust 有 ‘?’ 这个 bug 级语法糖。

go 代码里面,最多的 err 处理方式,也就是直接抛给上级,而这个刚好 ‘?’ 可以解决。
有了这个,多了不敢说,60% 的 if err != nil 还是可以消除的。
并且可以很爽的玩起链式调用了,目前随便来个 err 处理,就会打断链式调用

个人觉得 go 没必要用语法糖。

if err != nil 够用

返回值通常都得考虑,这样思维强制必须处理错误,不容易出现那种出错了还往下走的情形

这个就是见仁见智而已, 不喜欢也正常,或许 rust 那样的适合您的口味

这个喷的好。。求标准库源码做例子,观摩观摩。

异常不也是一样要考虑?这不算优点。

出异常的地方通常都跟处理的地方离远了,思维不连续,并且异常容易混一起,也让人很容易偷懒

rust 里面是学习 haskell 的 monad,除非你是消费以及最终求值的阶段,否则不会有人会去用 match 来处理错误。
rust 的错误处理最大的优势就是,之前步骤的异常,并不会影响你的业务逻辑,以及强制错误处理。你完全可以使用 and_then 或者 map 方法对一个 Result 进行结果转换,完全不用什么 match。?只是一个相对简洁的语法糖,就算不用 rust 也比现有的什么异常以及返回值优秀。
当然你不了解 monad,强制每一步都 match 一下,那就认为 rust 也是返回值吧。毕竟宝马跟单车都是靠轮子走的,而且都是圆的。




<br>// Serve a new connection.<br>func (c *conn) serve(ctx context.Context) {<br> c.remoteAddr = c.rwc.RemoteAddr().String()<br> ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())<br> defer func() {<br> if err := recover(); err != nil &amp;&amp; err != ErrAbortHandler {<br> const size = 64 &lt;&lt; 10<br> buf := make([]byte, size)<br> buf = buf[:runtime.Stack(buf, false)]<br> c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)<br> }<br> if !c.hijacked() {<br> c.close()<br> c.setState(c.rwc, StateClosed)<br> }<br> }()<br>

err 真这么好干嘛到处 recover ?

h__t__t__p__s:\golang.org\src\net\http\server.go

冒失没有手机号不让发 url


// Serve a new connection.
<br>func (c *conn) serve(ctx context.Context) {<br> c.remoteAddr = c.rwc.RemoteAddr().String()<br> ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())<br> defer func() {<br> if err := recover(); err != nil &amp;&amp; err != ErrAbortHandler {<br> const size = 64 &lt;&lt; 10<br> buf := make([]byte, size)<br> buf = buf[:runtime.Stack(buf, false)]<br> c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)<br> }<br> if !c.hijacked() {<br> c.close()<br> c.setState(c.rwc, StateClosed)<br> }<br> }()<br>


我觉得能写好 promise 的人一定能用 async/await,但是不会用 async/await 的肯定 promise 也不懂。
而且还有 async 属于新标准,很多人不一定知道并且用过……

xerrors 可以输出栈了,所以都还好…泛型比较重要一些

这个就是多返回值语言的优点,明明可以直接 return 多方便,try catch 和 defer 一样,只会让程序变得更慢。
defer 为了关闭资源还可以理解,而明明知道有 error,不直接处理,还在一堆代码里面 catch,不如直接 return 来的高效。

go 现在的多返回值实现是用栈来实现的,没办法像 c/c++用 rax 返回,速度慢了一大截。

err 或者 panic 都可以用,个人是喜欢 err, 但是有人喜欢用 panic,你也没办法,毕竟这里没有对错,只是风格喜好不同, 如果你调用的模块(库)用了 panic,只有 recover 应对, 自己写的几年 go 没用过 panic,但 recover 有时还是得用

所以说我观察下来就是能写写 promise 但一换 async await 就不行了的人挺多的。反过来 async await 写的好的,换 promise 也能写,就是幸福指数下降罢了,也就是说 async await 带来的字面上的简单让不少人误以为自己能轻松把异步代码写好了(然而并不)

我觉得 golang 关于语法糖的思路也是有这种拒绝虚假的幸福指数的倾向,不做让复杂的事情(异步/错误处理)表面上变简单,但并不降低实际复杂度的语法糖

我认为就是 fp 那一套而已,本身没有区别,各种 or_else, map_err 我是没有看出什么优雅来,如果没有编译器优化,甚至效率都低下

clear is better than clever,越是复杂的东西,推广和维护成本就越高,foo("".into()),我特么找个实现要到处去翻

本来编译器的目标之一就是优化- = -

try catch 没什么卵用. 用 go 写 crud 的会感觉 try 必要性比较大, 用 go 写偏系统一点的东西, try 基本上没卵用了.

rust 宣称的无数据竞争,仅仅是靠不可变来实现,这叫解决问题吗?根本就是回避问题,如果确实需要多线程共享变量,到头来还是要靠锁,rust 会打广告是真的

别吹,go 标准库是偏系统没有 crud 吧?里面也一堆 panic/recover 当 try catch 用

不可变对象就是解决的数据竞争,代码如果是 immutable 风格的就是天然不存在并发问题的。至于线程间数据共享你认为还要上锁,是因为你用了 immutable 的 rust 写出了 java/c++的代码,不可变对象是通过 copy on read/write 来解决并发问题的。理论上不存在两个线程共享一个引用的问题

Mutex,Arc、Rc、RefCell 是什么?什么叫“理论上不存在两个线程共享一个引用的问题“?真以为 rust 的 ownership 能解决所有问题?

async/await 是帮你做 CPS,这个是有一定复杂性的,已经超过了语法糖的范畴了。

你确定吗……反正我遇到的真实业务里能用 promise 写清楚一个稍微复杂点逻辑的比 aa 少多了……虽然不深入了解 promise 的人对 aa 也就停留在最简单的使用上,但至少他们能用这个写出代码……

另外我倒是认为这个没必要关注也没必要吵,因为用 Go 的其实并不关注这些东西,关注这些东西的不用 Go。吵半天一点意义都没有

写一些简单的并发和错误处理,面试过程中可能是本能以为 async/await 简单,会有人准备要用,然而最终很少有人能写出来,基本都要让他们回到用 promise 的路上

哦,如果你是说用 await 把所有的并发都变成串行也算是写出代码的话,那可能是 async/await 更容易让人写出代码

#61
为什么要把并发改写成串行?不明白你的逻辑。从使用成本上,promise 比 aa 高是很明显的事实。

老哥受了什么刺激,为什么要对牛谈琴呢

我不知道你所谓的”用 async-await 写清楚”是什么意思,但是很明显的 Promise 和 async-await 不是替代关系,从能力上来说 async-await 还要比你 Promise 弱,只用 async-await 写逻辑当然是无法做到的

昨天刚投了反对票,宁愿用现在也不想要这个 try

废话,rust 本来就是函数式近亲属,部分特性都是从 Haskell 弄过来的

我只是发了一次言,其实还好。我只是说明一下这东西的优势在哪里,为什么 Monad 是更好的异常处理而且。毕竟一次回复不仅仅是一个人看到。大家也可以看到。大家各取所需,觉得 golang 好的就继续写,觉得其他更好的就去写其他就好了。我觉得没什么必要纠结什么天下第一,毕竟电锯跟锤子不一样,CNC 机床也不能替代凿子。当然爱一样东西,自己能出力去让它变得更好,这样也不错。

我最不能理解的是变量在左类型在右,我是真特么别扭

还有一个接口的实现,不指定接口,需要参数类型相同,真尼玛傻吊



try(try(try(try(try(try(try(try(try(try(f()))))))))))


除非 f 的返回类型是 val, err, err, err, err, err, err, err,这个时候更应该关注的的是写 f()的人而不是 try()这个语法糖

更有意义的例子应该是

foo(try(bar(try(baz()))))


你的话题从错误处理转进到多线程编程了。
我可以理解为你已经承认了自己在错误处理上对于 Rust 的错误认识么?
毕竟已经不正面回应,而是开始转到下一个话题了。

我想表达的不是你说的意思,而是看不惯 rust 吹,至于错误处理,err,exception,monad 没有哪个有绝对优势,但是 rust 粉的说话方式总是居高临下

也不清楚你的第二句话是根据何种理论得出的

我只知道我用 rust 唯一不满的是还没有 stable async 和 windows mio

而且 rust 和 go 走的道路本身就不一样 有不同的情景可以用不同的工具 不好🐎?

https://github.com/golang/go/wiki/PanicAndRecover wiki 里都教你怎么用了,自己不知道,就说“偷偷”,呵呵。

这里用 recover 有什么问题?如果代码有 bug,例如 slice 越界,recover 就可以保证其他连接不受影响。panic / recover 本来就是这样用的。

针对Golang Go语言社区否决了新的try语句提议这一话题,以下是我的专业回复:

Go语言社区在近期否决了关于内置try错误检查函数的提案。这一决定是由Go语言开发团队的提案审查委员会做出的,并得到了社区压倒性的反馈支持。

try语句的提案旨在简化Go语言中的错误处理流程。例如,原代码f, err := os.Open(filename); if err != nil { return …, err }可以通过try语句简化为f := try(os.Open(filename))。然而,尽管这种方法看起来能够减少样板代码,但社区和开发团队认为它并未从根本上解决错误处理的问题,且可能对API的直观性产生负面影响。

此外,try语句被视为一种针对特定任务的“语法糖”,它并不适用于所有错误处理情况。Go语言的设计哲学强调简单明了,而try语句的引入可能会使错误处理机制变得复杂和混乱。

综上所述,Go语言社区否决try语句的提议是出于对语言设计哲学的坚守和对错误处理机制的深思熟虑。这一决定有助于保持Go语言的简洁性和一致性,为开发者提供更好的编程体验。

回到顶部