大家好,我是煎鱼。

最近社区的同学和 Go 官方又因为错误处理的提案屡屡被否,发生了一些小的摩擦。也非常难得的看到核心团队成员首次表达了目前的态度和情况。

基于此,我们今天进行该内容分享。紧跟 Go 官方最新进展。

快速背景

Go 的错误处理机制,主要是依赖于 if err != nil 的方式。因此在对函数做一定的封装后。

代码会呈现出以下样子:


jy1, err := Foo1()
if err != nil {
    return err
}
jy2, err := Foo2()
if err != nil {
    return err
}
err := Foo3()
if err != nil {
    return err
}
...

有部分开发者会认为这比较的丑陋、混乱且难以阅读。因此 Go 错误处理的优化,也是社区里一直反复提及和提出的领域。饱受各类争议。

新提案:追求类似 try-catch

最近一位国内的同学 @xiaokentrl 提了个类似 try catch error 的新提案,试图用魔法打败魔法。

原作者给出的提案内容是:

1、新增环境变量做开关:

ERROR_SINGLE = TRUE   //error_single = true

2、使用特定标识符来做 try-catch:

Demo1 单行错误处理:

//Single-line error handling
file, err := os.Create("abc.txt") @ return nil , err
defer file.Close()

Demo2 多行错误处理:

func main() {
    //Multiline error handling
    :@

    file, err:= os.Open("abc.txt")
    defer file.Close()

    buf := make([]byte, 1024)
    _, err2 := file.Read(buf)

    @ err | err2  return ...
}

主要的变化内容是:利用标签 @ 添加一个类似 try-catch 的代码区块,并添加运算符和相关错误处理的联动规则。

这个提案本身,其实就是以往讲到的 goto error 和 check/with 这种类似 try-catch 的模式。

当然非常快的就遭到了 Go 核心团队的反对:

@Ian Lance Taylor 表示:由于很难处理声明和应用,如果一个标签的作用域中还有其他变量,就不能使用 goto。

新的争端:官方你行你上

社区中有同学看到这一次次被否的错误处理和关联提案们,深感无奈和无语。他发出了以下的质疑:

“为什么不让 Ian Lance Taylor 和/或 Go 核心团队的其他成员提出改进的错误处理框架的初始原型,然后让 Go 社区参与进来,为其最终形式做出贡献呢?Go 中的泛型正是这样发展到现在的。

如果我们等待 Go 社区提出最初的原型,我认为我们将永远不会有改进的 Go 错误处理框架,至少在未来几年内不会。”

但其实很可惜,因为人家真干过。

Go 核心团队是有主动提出过错误处理的优化提案的,提案名为《Proposal: A built-in Go error check function, try》,快速讲一下。

以前的代码:

f, err := os.Open(filename)
if err != nil {
    return …, err  // zero values for other results, if any
}

应用该提案后的新代码:

f := try(os.Open(filename))

try 只能在本身返回错误结果的函数中使用,且该结果必须是外层函数的最后一个结果参数。

不过很遗憾,该官方提案,喜提有史以来被否决最多的提案 TOP1:

最终该提案也由于形形色色的意见,最终凉了。感觉也给 Go 核心团队泼了一盆凉水,因为这是继 check/handle 后的 try,到目前也没有新的官方提案了。

Go 官方回应

本次提及的新提案下,大家的交流愈演愈烈,有种认为就是 Go 核心团队故意不让错误处理得到更好的改善。

此时 Go 核心团队的元老之一 @Ian Lance Taylor 站出来发声,诠释了目前 Go 团队对此的态度。这也是首次。

具体内容如下:

“我们愿意考虑一个有良好社区支持的好的错误处理提案。

不幸的是,我很遗憾地说,基本上所有新的错误处理提案都不好,也没有社区支持。例如,这个提案有 10 个反对票,没有赞成票。我当然会鼓励人们在广泛使用这门语言之前,避免提交错误处理提案。

我还鼓励人们审查早期的提案。它们在这里:https://github.com/golang/go/issues?q=label%3Aerror-handling+ 。目前已有 183 个并在不断增加。

我自己阅读了每一个。重要的是,请记住,对已被否决提案的微调的新提案也几乎肯定也会被否决。

并且请记住,我们只会接受一个与现有语言契合良好的提案。例如:这个提案中使用了一个神奇的 @ 符号,这完全不像现有语言中的任何其他东西。

Go 团队可能会在适当的时候提出一个新的错误处理提案。然而,正如其他人所说,我们最好的想法被社区认为是不可接受的。而且有大量的 Go 程序员对现状表示满意。”

总结

目前 Go 错误处理的情况和困境是比较明确的,很多社区同学会基于以往已经被否决的旧提案上进行不断的微改,再不断提交。

现阶段都是被全面否定的,因为即使做了微调,也无法改变提案本身的核心思想。

而 Go 官方自己提出的 check/handle 和 try 提案,在社区中也被广大的网友否决了。还获得了史上最多人否决的提案的位置。

现阶段来看,未来 1-3 年内在错误处理的优化上仍然会继续僵持。

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blog 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

推荐阅读


煎鱼
8.4k 声望12.8k 粉丝