这是我参与「第五届青训营 」笔记创作活动的第4天
笔者才学疏浅,如有问题请指出。
前言
我们都知道,代码的编写质量决定了程序是否好维护以及是否能够很好的运行,也会在一定程度上影响程序的性能。本文章主要记录笔者学习高质量编程的内容。
高质量编程
什么是高质量代码
- 代码能够达到正确可靠、简洁清晰的目标。
- 各种边界条件是否考虑完善。
- 异常处理情况、稳定性。
- 可读性和可维护性强。
遵循原则
尽管各语言语法不同,但高质量编程所遵循的原则是相通的。
- 简单性:消除多余的复杂性,以简单清晰的逻辑写代码,不理解的代码无法修复改进。
- 可读性:机器识别的是二进制码,代码是给人看的,编写可维护的代码首先保证代码可读。
- 生产力:团队整体的工作效率非常重要。
编码规范
- 代码格式
- 注释
- 命名规范
- 控制流程
- 错误和异常处理
代码格式
- go的代码格式推荐使用官方提供的gofmt工具自动将格式化为官方统一风格,常见的IDE都支持配置。
- 也可以使用gomports工具,等于gofmt加上依赖包管理,自动增删依赖包引用,将依赖包按字母排序并分类。
注释
代码是最好的注释。
- 注释应该解释代码作用:适合注释公共符号。
- 注释应该解释代码如何做的:适合解释实现过程。
- 注释应该解释代码实现原因:适合解释代码的外部因素提供额外上下文。
- 注释应该解释代码什么情况下会出错:适合解释代码的限制条件。
公共符号始终要注释
- 包括变量声明的每个公共符号:变量、常量、函数以及结构体都需要添加注释。
- 任何既不明显也不简短的公共功能必须给以注释。
- 无论长度和复杂度,读库中的函数都必须进行注释。
- 对于公共符号都要有注释说明。
命名规范
- 简洁胜于冗长。
- 缩略词全大写,当位于变量开头其不需要导出时全小写:使用ServeHTTP而不是ServeHttp。
- 变量距离其被使用的地方越远,则需要携带更多的上下文信息。
function
- 函数名不携带包名的上下文信息,包名和函数总是成对出现的。
- 函数名尽量简短。
- 当名为foo的包某个函数返回类型为Foo时可以省略类型信息而不导致歧义。
package
- 小写字母组成,不含大写字母和下划线。
- 简短并包含一定的上下文信息,如:task等。
- 不要与标准库同名。
控制流程
- 线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支。
- 正常流程代码沿着屏幕向下移动。
- 提升代码的可维护性和可读性。
- 故障问题大多数出现在复杂的条件语句和循环语句中。
错误和异常处理
简单错误
- 简单的错误指仅出现一次的错误,且在其他地方不需要捕获该错误。
- 优先使用error.New来创建匿名变量直接表示简单错误。
- 如有格式化需求使用fmt.Errorf。
错误的Wrap和Unwrap
- 错误的Wrap实际上是提供了一个error嵌套另一个error的能力,从而生成一个error跟踪链。
- 在fmt.Errorf中使用%w关键字将一个错误关联至错误链中。
错误判定
- 判定一个错误是否为特定错误用error.Is。
- 不同于==,使用error.ls方法可以判定错误链上的所有错误是否含有特定错误。
- 在错误链上获取特定种类的错误用error.As。
panic
- 不建议在业务代码中使用panic,调用函数不包含recover会造成程序崩溃,若问题可以被屏蔽或解决建议使用error代替panic。
- 当程序启动阶段发生不可逆转的错误时可以在init或main函数中使用panic。
recover
- recover只能在被defer的函数中使用。
- 嵌套无法生效。
- 只在当前goroutine生效。
- defer语句后进先出。
小结
写一个漂亮的代码能使我们看起来更好理解(可读性),也能在修改代码的时候更方便(可维护性)。高质量编程不仅仅能用到go里面,几乎所有编程语言都可以使用这样的一套规范,能够规范自己的代码也是一种能力的提升。
参考
字节跳动青训营Go的高质量编程课程