Go 错误处理:用 select-case 来解决这个难题?

大家好,我是煎鱼。

日常看 Go 社区的一些新动态,发现大家对于错误处理的新提案是很积极。上次分享了一篇想要用 switch-case 来解决现状的新提案,不少同学认为不可行。

没想到 Go 社区的同学脑洞还是很大的,这几天又整出来个 select-case 的新提案的方式来解决错误处理。

今天基于此给大家分享一下社区里的新脑洞。

快速背景

本节的背景主要是给不了解的同学拉通一下。如果已经知道的可以跳过本节。新提案的提出背景,与之前的类似。

社区内的 Go 开发者很多嫌弃 if err != nil 的错误处理方式过于繁琐,纷纷提出各种改进方式和新提案。截至目前暂无大改进被通过。

具体演示代码如下:

go 复制代码
func CopyFile(src, dst string) error {
 r, err := os.Open(src)
 if err != nil {
  return err
 }
 defer r.Close()

 w, err := os.Create(dst)
 if err != nil {
  return err
 }
 defer w.Close()

 if _, err := io.Copy(w, r); err != nil {
  return err
 }
 if err := w.Close(); err != nil {
  return err
 }
 // 和煎鱼一起煎个鱼...
}

要写比较多的判断和返回错误的逻辑,并且这些代码比正式的调用代码还要多。所以也常被人戏称一个 Go 工程里 80% 都是 if err != nil 等错误检查代码。

新提案

本次新提案是由 @bjorndm 提出的 《proposal: Go 2: add trap on direct assignment with select block》:

提出者本身使用编程语言的经验比较丰富,用过:C, Ruby, Pascal, Basic, Java, Shell 等。本次提出该提案的原因是某些 shell 中 trap 语句的启发。

抽象了一下,提案内容如下:

  1. 功能上是要扩展 select 关键字的语法,允许在 select 关键字和其代码块之间放一个单独的变量,这会在变量上安装一个 "陷阱"(类似触发器)。
  2. 这个 "陷阱" 是关键点,当任何值被赋给该变量时将会触发。然后在 select 代码块的主体中,case 语句可用于检查变量的值。

从原作者的描述来看,提案内容比较生硬。我们结合演示代码来看就知道,他是想构思什么新语法来使用 select-case 达到错误处理的目的了。

演示代码如下:

go 复制代码
func CanFail(name string) error {
var err error
select err {
      case err != nil:
          return fmt.Errorf("CanFail: %w", err)
}

fin, err := os.Open(name)

buf, err := io.ReadAll(fin)

return nil
}

结合新提案的语法,由于 select 代码块中是一个变量,符合新语法 "陷阱" 的场景。

因此 err 变量被安装了 "陷阱",当后面的 os.Openio.ReadAll 等方法赋值给 err 变量时,就能触发 select 子句的 case 检查。

最终以此达到简化 if err != nil 的目的。也可以满足 Go1 兼容性保障,达到向前和向后兼容,不需要新增关键字。

总结

截止目前我们已经看过了许多 Go 错误处理的脑洞新提案。本提案是期望利用 select-case 的特性结构来做扩展,以此达到向前兼容的目的。

从编译和运行上,作者认为代价是比较小的,只需要在内部替换成类似 switch 的效果就可以了。

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

推荐阅读

相关推荐
煎鱼eddycjy7 小时前
新提案:由迭代器启发的 Go 错误函数处理
go
煎鱼eddycjy7 小时前
Go 语言十五周年!权力交接、回顾与展望
go
不爱说话郭德纲1 天前
聚焦 Go 语言框架,探索创新实践过程
go·编程语言
0x派大星2 天前
【Golang】——Gin 框架中的 API 请求处理与 JSON 数据绑定
开发语言·后端·golang·go·json·gin
IT书架2 天前
golang高频面试真题
面试·go
郝同学的测开笔记2 天前
云原生探索系列(十四):Go 语言panic、defer以及recover函数
后端·云原生·go
秋落风声3 天前
【滑动窗口入门篇】
java·算法·leetcode·go·哈希表
0x派大星5 天前
【Golang】——Gin 框架中的模板渲染详解
开发语言·后端·golang·go·gin
0x派大星5 天前
【Golang】——Gin 框架中的表单处理与数据绑定
开发语言·后端·golang·go·gin
三里清风_6 天前
如何使用Casbin设计后台权限管理系统
golang·go·casbin