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 催更。

推荐阅读

相关推荐
名字还没想好☜11 小时前
Go context.AfterFunc 实战(Go 1.21):context 一取消就自动跑清理,告别手写 goroutine 监听 Done
后端·golang·go
liyinchi19882 天前
微信小程序支付遇到“由于小程序违规,支付功能暂时无法使用” 解决办法
java·微信小程序·go
天天喝旺仔2 天前
Go 泛型实战:从类型参数、约束到可复用泛型容器与函数
数据结构·算法·容器·go
gospace3 天前
【无标题】
go·gb28181·gowvp
我不会起名字3223 天前
一天一道算法题(35):电话号码的字母组合
java·数据结构·后端·python·leetcode·go·回溯
江湖十年3 天前
Go GOPROXY 兜底链的坑:从一次诡异的 CI lint 失败说起
后端·面试·go
秋风点枝4 天前
gogogo!go语言感悟大观--打卡day01
go·devops
探索云原生4 天前
KubeClipper 1.7.0 发布:Operation 优化与 Kubernetes 1.37 支持
linux·docker·云原生·kubernetes·go
右耳朵猫AI4 天前
Go周刊2026W37 | Ebitengine 纯 Go 化、simd 重写 TurboPFor、json/v2 落地
后端·微服务·go
福兮说4 天前
Gin 项目里的错误处理:让 Controller 不必知道错误是怎么来的
后端·go·gin·架构设计