这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天
一、本堂课重点内容:
- 高质量编程
- 小测
二、详细知识点介绍:
- 高质量编程
1.2.4 编码规范——控制流程
避免嵌套,保持正常流程清晰
例子:
如果两个分支中都包含return语句,则可以去除冗余的else。
尽量保持正常代码路径为最小缩进
- 优先处理错误情况/特殊情况,尽早返回或继续循环来减少嵌套。
例子:
在该例子中:
- 最常见的正常流程的路径被嵌套在两个if条件内
- 成功的退出条件是
return nil,必须仔细匹配大括号来发现 - 函数最后一行返回一个错误,需要追溯到匹配的左括号,才能了解何时会触发错误
- 如果后续正常流程需要增加一步操作,调用新的函数,则又会增加一层嵌套
调整后:
GO仓库中的例子:
在该例中,对于异常情况会提前返回,在异常情况处理完成后进入正常的处理流程。
小结
- 线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支
- 正常流程代码沿着屏幕向下移动
- 提升代码可维护性和可读性
- 故障问题大多出现在复杂的条件语句和循环语句中
1.2.5 编码规范——错误和异常处理
简单错误
- 简单的错误指的是仅出现一次的错误,且在其他地方不需要捕获该错误
- 优先使用
errors.New来创建匿名变量来直接表示简单错误 - 如果有格式化的需求,使用
fmt.Errorf
例子:
错误的Wrap和UnWrap
- 错误的Wrap实际上是提供了一个error嵌套另一个error的能力,从而生成一个error的跟踪链
- 在fmt.Errorf中使用
%w关键字来将一个错误关联至错误链中
Go1.13在errors中新增了三个新API和一个新的format关键字,分别是errors.Is、errors.As、errors.Unwrap以及fmt.Errorf的%w。如果项目运行在小于Go1.13的版本中,导入golang.org/x/xerrors来使用
例子:
错误判定
- 判定一个错误是否为特定错误,使用
errors.Is - 不同于使用
==,使用该方法可以判定错误链上的所有错误中是否含有特定的错误
例子:
- 在错误链上获取特定种类的错误,使用
errors.As
例子:
panic
- 不建议在业务代码中使用panic
- 调用函数不包含recover会造成程序崩溃
- 若问题可以被屏蔽或解决,建议使用error代替panic
- 当程序启动阶段产生不可逆转的错误时,可以在init或main函数中使用panic
例子:
recover
- recover只能在被defer的函数中使用
- 嵌套无法生效
- 只在当前goroutine生效
- defer 的语句是后进先出
例子:
- 如果需要更多的上下文信息,可以recover后在log中记录当前的调用栈
例子:
小结
-
error尽可能提供简明的上下文信息链,方便定位问题
-
panic用于真正异常的情况
-
recover生效范围:在当前goroutine的被defer的函数中生效
-
小测
哪种命名方式更好?
①:
第一种更好,详见下图实际调用时的结果:
②:
第二种更好,因为第一种省去了应有的信息。
程序的输出是什么?
- defer语句会在函数返回前调用
- 多个defer语句是后进先出
最终输出:31
三、引用参考: