当前位置: 首页 > news >正文

golang提案,内置 Go 错误检查函数

先来狠狠吐个槽

要吐槽 Go1 的 error ,那咱得先整明白大家为啥都猛喷它的错误处理做得不咋地。在 Go 语言里头,error 本质上其实就是个 Error 的接口:

type error interface {Error() string
}

实际的应用场景如下:

func main() {x, err := foo()if err != nil {// handle error}
}

单瞅这个例子,感觉好像没啥大毛病,可要是工程规模一变大,那可就不得了啦!

很明显,if err!= nil 这种逻辑在工程代码里那是扎堆出现,Go 代码里的 if err!= nil 甚至能占到工程代码量的 30% 还多呢:

func main() {r1, err := fun1()if err != nil {// handle error}r2, err := fun2()if err != nil {// handle error}r3, err := fun3()if err != nil {// handle error}r4, err := fun4()if err != nil {// handle error}
}

猛这么一对比,4行函数调用,12行错误处理,这可真是让人头大呀!

另外呀,既然是错误处理,那肯定不只是简简单单地return err 这么回事儿。在工程实践中,项目代码那都是层层嵌套的,如果直接写成:

if err != nil {return err
}

在实际工程里,这可绝对不行。您说您咋能知道具体是哪儿抛出的错误信息呀,实际出错的时候那只能是瞎蒙乱猜。所以就得加上各种描述信息:

if err != nil {return fmt.Errorf("xxx, error: %s", err.Error())
}

try 函数

在 golang 的提案里,介绍了一种新的内置函数“try”,这小家伙的出现是为了简化 Go 程序里那让人头疼的错误处理流程,同时还能保住语言的简洁明快和直截了当。try提供了一种神奇的机制,能让常见的错误检查模式表达得更简洁明了,把那些烦人的样板代码都给减少了,让代码的可读性和可维护性都蹭蹭往上涨。

虽说当前 Go 语言通过返回错误作为结果来处理错误的方式简单又灵活,但是在实际操作中,大量的错误检查代码常常让代码变得又长又复杂,就像一团乱麻,让人很难快速搞懂其中的逻辑流程。特别是在函数链里有好几个可能返回错误的步骤时,错误传播和处理的代码能占程序的一大部分,简直是“鸠占鹊巢”。

try 表达式

引入了一个新的内置函数try,它接收一个可能返回错误的表达式当参数,要是这个表达式执行成功(也就是没返回错误),那就返回表达式的值。要是表达式返回了一个错误,那try会立马“翻脸”,终止当前函数的执行,把错误毫不留情地返回给调用者。它的语法是这样的:

result := try expression
x1, x2, … xn = try(f())

等同于下面的代码

t1, … tn, te := f()  // t1, … tn, te are local (invisible) temporaries
if te != nil {err = te     // assign te to the error result parameterreturn       // return from enclosing function
}
x1, … xn = t1, … tn  // assignment only if there was no error

demo

来瞧瞧下面这个例子,展示了咋用try来简化文件读取操作的错误处理:

func ReadData(filename string) ([]byte, error) {f, err := os.Open(filename)if err != nil {return nil, err}defer f.Close()data, err := ioutil.ReadAll(f)if err != nil {return nil, err}return data, nil
}

try可以简化成这样:

func ReadData(filename string) ([]byte, error) {f := try os.Open(filename)defer f.Close()data := try ioutil.ReadAll(f)return data, nil
}

总结

  • 错误传播:try直接就让包含它的函数“缴械投降”,然后返回错误,这就意味着它不能用在错误发生后还想“垂死挣扎”继续执行的场景里。
  • 控制流影响:因为try导致的提前“打退堂鼓”,开发者得瞪大眼睛留神它对局部变量的生命周期和资源管理的影响。
  • 简洁与清晰:虽说try减少了错误检查的显式代码,可要是过度使用,可能会影响代码的可读性,特别是在复杂得像迷宫一样的逻辑里。

try这个内置函数是对 Go 错误处理模型的一个补充,目标就是提供一种更简练的错误处理方式,同时保持语言的其他核心特性不变。

资料

  • https://github.com/golang/go/issues/32437
  • https://github.com/golang/proposal/blob/master/design/32437-try-builtin.md

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【前端】NodeJS:记账本案例优化(token)
  • leetCode - - - 双指针
  • 解密JVM崩溃(Crash)-学习笔记
  • qt-12工具盒(ToolBox)
  • 数学基础 -- 指数增长与指数衰变
  • 使用Go语言将PDF文件转换为Base64编码
  • Wireshark分析工具
  • 构建艺术:Ruby中RESTful API的精粹实践
  • 【IDEA】idea配置服务器没有tomcat
  • 【Django开发】前后端分离django美多商城项目第1篇:欢迎来到美多 项目主要页面介绍【附代码文档】
  • SpringBoot-01-全局异常处理器
  • Docker 部署 XXL-JOB
  • fastzdp_sqlmodel框架是如何实现更新和删除相关的功能封装的,20240817,Python的国产新ORM框架
  • 对外提供开放式数据查询使用什么数据存储?
  • 蚂蚁AL1 15.6T 创新科技的新典范
  • 自己简单写的 事件订阅机制
  • “大数据应用场景”之隔壁老王(连载四)
  • 2017-08-04 前端日报
  • centos安装java运行环境jdk+tomcat
  • Django 博客开发教程 16 - 统计文章阅读量
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • ES6之路之模块详解
  • express.js的介绍及使用
  • FineReport中如何实现自动滚屏效果
  • Git同步原始仓库到Fork仓库中
  • Go 语言编译器的 //go: 详解
  • java8 Stream Pipelines 浅析
  • java小心机(3)| 浅析finalize()
  • js对象的深浅拷贝
  • Laravel5.4 Queues队列学习
  • mysql常用命令汇总
  • quasar-framework cnodejs社区
  • react 代码优化(一) ——事件处理
  • SQL 难点解决:记录的引用
  • use Google search engine
  • Web设计流程优化:网页效果图设计新思路
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 【干货分享】dos命令大全
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • ​低代码平台的核心价值与优势
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (26)4.7 字符函数和字符串函数
  • (27)4.8 习题课
  • (SpringBoot)第二章:Spring创建和使用
  • (超详细)语音信号处理之特征提取
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (计算机网络)物理层
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (一)80c52学习之旅-起始篇
  • (转)平衡树