Redian新闻
>
Go新提案:返回值应该明确使用或忽略?

Go新提案:返回值应该明确使用或忽略?

公众号新闻

之前在写 Go 代码时 IDE 经常会提示。外加我有一个朋友他团队内 CodeReview 也会遇到一些方法的返回值,处理不处理的问题。一开始大家还会讨论一下,久而久之基本也就麻木了。

假期时翻资料学习时,看到了 Go 社区这个相关的 issues#20803[1]。之前已经有大佬提过类似的疑惑,Go 团队也进行了回复。

官方算是给了一个初步的定论,今天分享给大家。和煎鱼一起学习!

快速背景

现在我们写 Go 程序时,如果函数或方法同时返回了返回值和错误参数,用户(程序员)必须要做出一些处理。

最经常的返回 error 参数的场景。如下代码:

v, err := computeTheThing()

或是明确的忽略他。如下代码:

v, _ := computeTheThing()

相信大家都这么干过。(没错,经常翻代码看到...)

但是在很多有唯一返回值(例如:io.Closer.Closeproto.Unmarshal)的场景下,写习惯后,有的就顺手忽略了。

最常见的代码:

_ = json.Unmarshal(jsonBlob, &eddycjy)

又或是:

defer fd.Close()

看了直呼好家伙...业务代码写的久的同学应该知道不可信任原则。我是经常遇到有人这么写,结果没有记错误信息,查半天没查到哪里出问题的。

即使不是错误参数的处理。在其他 API 中也有类似的问题。

如下代码:

t := time.Now()
t.Add(10 * time.Second)  // Should be t = t.Add(…)

又或是:

strconv.AppendQuote(dst, "eddycjy")  // Should be dst = strconv.AppendQuote(…)

总而言之,提案作者 @Bryan C. Mills 认为 “忘记” 进行错误检查或丢弃赋值的后果可能相当严重。

可能会出现如下问题:存储到生产数据库中的数据被破坏、用户数据无法提交到存储中、因未验证用户输入而导致程序崩溃等问题。

期望的解决方案

提案作者 @Bryan C. Mills 给出思路:建议 Go 默认拒绝未使用的返回值。

配合的解决方式是增加 ignore 内置关键字或其他方式来忽略任意数量的返回值。

如下 ignore 代码:

go func() { ignore(fmt.Fprintln(os.Stderr, findTheBug())) }()

或是以下变形:

go func() { ignore fmt.Fprintln(os.Stderr, findTheBug()) }()

又或是使用别的方式:

go func() { _ fmt.Fprintln(os.Stderr, findTheBug()) }()

简而言之,就是较为显式的指定来忽略。

其他语言是如何处理的

  • Swift 会对未使用的返回值发出警告,但如果设置了 @discardableResult 属性,则允许抑制该警告。
    • 在 Swift 3 中进行修改之前,默认情况下可以忽略返回值(但可以使用 @warn_unused_result 添加警告)。
  • Rust 有 #[must_use][2] 属性。
  • C++17 有 [[nodiscard]][3] 属性,它将长期存在的 __attribute__((warn_unused_result)) GNU 扩展标准化。
  • ghc Haskell 编译器为未使用的结果提供了警告标志(-fwarn-unused-do-bind 和 -fwarn-wrong-do-bind[4])。
  • OCaml 默认会对未使用的返回值发出警告。它在标准库中提供了一个 ignore[5] 函数。

提案作者认为 OCaml(这是一个函数式、指令式、模块化、面向对象的通用的编程语言)提供 ignore 函数的方式与 Go 最为贴合。

因此他提出的提案和方向也与此语言保持基本一致。

核心团队回复

Go 核心团队成员之一的老大哥 @Ian Lance Taylor 和 Go 创始人 @ Rob Pike,直接发了张好人卡给提案作者。(尴尬了...)

翻译过来的关键意思是:“我很同情大家的担忧,但你这个解决方案不够好”。

反对的原因是:

  • 降低代码可读性:认为用 ignore 函数来包装表达式会掩盖代码的主要内容,从而增加代码的阅读难度。
  • 这个例子不够好:在一门重视简洁性的语言中,用 _, _ = 开头的典型例子 hello, world 在我看来是很不幸的。

结论是:“我同意这个问题,但不同意建议的解决方案”。(煎鱼注:高情商发言人?)

总结

通篇看下来,其实 Go 核心团队是较为认可这个问题的存在。但是既要也要还要的模式下,一时半会也找不到更好的解决思路。

同时许多社区内提出的解决思路都会一定程度的破坏 Go 现有的兼容性保障,让这件事变得前后都 “复杂” 了起来。

因此在后续中,Go 官方更推荐使用 vet 等 linter 工具检测来规避这个问题。

推荐阅读

参考资料
[1]

issues#20803: https://github.com/golang/go/issues/20803

[2]

#[must_use]: https://doc.rust-lang.org/std/result/#results-must-be-used

[3]

[[nodiscard]]: https://en.cppreference.com/w/cpp/language/attributes

[4]

-fwarn-unused-do-bind 和 -fwarn-wrong-do-bind: https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/options-sanity.html

[5]

ignore: https://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
相当炸裂啊!加州新提案:离开加州,要交“搬家税”!还要交10年……马上开始!COSTCO新三月特价福利提前开放,吃的穿的用的样式不少!今天是闰日太残忍!应该立刻禁用老鼠胶陷阱!?纽约议员提出法案,要禁止销售和使用!纽约地铁加强安全措施!首次引入武器检测系统以确保乘客安全加州|新提案,谷歌Google要向加州新闻媒体支付“使用费”?谷歌开始删除加州新闻源留学生如何正确使用OPT可以更大几率留在美国?美国会最新提案:把示威学生遣送到加沙【解字】闰日说“正闰”什么时候卖出红利策略?离开这个州还得交税?“搬家税”,一种政府“劫富济贫“的新策略?二岩藻糖基乳糖滴度超33g/L,中国农大团队提出高效从头合成HMO新策略,无副产物3-FL产生紧急通知!加拿大Costco新规严查:进门要做这事!华人炸锅!围墙边种什么树好?美本申请要不要讲策略?为防“零元购”,拼了!加州最新提案:各大零售店或关闭自助结账!呵呵!美国出了个奇葩新提案:犯罪分子出狱后,每人将获得2600美元“出狱费”!漂流四海的凌霄花(2)美国新提案!罪犯出狱后每人将获得$2600“出狱费”???​【社会】法国议员新提案:让小偷“露脸”!美国会最新提案:把美国“反以”大学生,送去加沙呆6个月!离开加州还得交税?“搬家税”,一种加州政府”劫富济贫“的新策略?离谱!美国会议提案:把示威大学生,送去加沙呆6个月!智慧医疗建设走过数据收集与治理阶段,正步入医疗数据价值应用“战场”东软集团:生成式 AI 时代,如何布局 AI 人力资源战略?| DTDS 全球数字人才发展大会美国这个州新提案:将禁止销售洗衣球、洗碗机球!网友:管太宽了吧量化选股策略介绍、回顾与展望什么是量化选股策略?美共和党提案:把参加挺巴抗议扰乱校园的大学生送去加沙!加州大学圣地亚哥分校还在闹,还要求罢免校长……美国这州新提案:将禁止销售洗衣球、洗碗机球!网友:管太宽了吧热热热!洛杉矶Costco新三月折扣同步大热促销中~美国这州出奇葩新提案:犯罪分子出狱后,每人将获得2600美元“出狱费”!加州正在起草法案:限制超市使用自助结账,“无人超市”在加州面临倒闭双林奇案录第三部之校园疑案:第十四节忍无可忍!国会最新提案:把美国“反以”大学生,送去加沙呆6个月!网友:培养恐怖分子?美国出了个奇葩新提案:犯罪分子出狱后,每人将获得2600美元“出狱费”!邯郸杀人案:法律不应该偏向邪恶凶手
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。