高质量编程|青训营笔记

38 阅读5分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天
主题:高质量编程与代码规范

高质量编程

(1)简介

什么是高质量?
编写的代码能够达到正确可靠、简洁清晰的目标可称之为高质量代码。 需要考虑:
各种边界条件是否考虑完备。 异常情况处理,稳定性保证。 易读易维护。

编程原则

实际应用场景千变万化,各种语言的特性和语法各不相同,但高质量编程遵循的原则是相通的。
简单性:消除多余的复杂性,以简单清晰的逻辑编写代码。不理解的代码无法修复改进
可读性:代码是写给人看的,而不是机器。编写可维护代码的第一步是确保代码可读。
生产力:团队整体工作效率非常重要。

(2)编码规范

如何编写高质量的Go代码?

代码格式

推荐使用gofmt自动格式化代码。
gofmt:Go语言官方提供的工具,能自动格式化Go语言代码为官方统一风格,常见IDE都支持方便的配置。
goimports:也是Go语言官方提供的工具,实际等于gofmt加上依赖包管理,自动增删依赖的包引用、将依赖包按字母序排序并分类。

注释

公共符号始终要注释: 包中声明的每个公共符号:变量、常量、函数以及结构都需要添加注释。
任何既不明显也不简短的公共功能必须予以注释。
无论长度或复杂程度如何,对库中任何函数都必须进行注释。
注释应该:解释代码作用、代码如何做、代码实现原因、代码什么时候会出错。
代码是最好的注释,注释应该提供代码未表达出的上下文信息。

命名规范

核心目标:
降低阅读理解代码的成本。
重点考虑上下文信息,设计简洁清晰的名称。
1.变量
简洁胜于冗长。
缩略词全大写,但当其位于变量开头且不需要导出的时候,使用全小写
例如使用ServerHTTP而不是ServerHttp、使用XMLHTTPRequest或者xmlHTTPRequest
变量距离其被使用的地方越远,则需要携带越多的上下文信息。
全局变量在其名字中需要更多的上下文信息,使得在不同地方可以轻易辨认出其含义。
2.函数
函数名不携带包名的上下文信息,因为包名和函数名总是同时成对出现的。
函数名尽量简短。
当名为foo的包某个函数返回类型Foo时,可以省略类型信息而不导致歧义。
当名为foo的包某个函数返回类型T时(T并不是Foo),可以在函数名中加入类型信息。
3.包
只由小写组成,不包含大写字母和下划线等字符。
简短并包含一定的上下文信息。例如schema、task等。
不要与标准库同名。
尽量满足:
不使用常用变量名作为包名。
使用单数而不是复数。
谨慎使用缩写。

控制流量

原则: 线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支。
正常流程代码沿着屏幕向下移动。
提升代码可读性和可维护性。
故障问题大多出现在复杂的条件语句和循环语句中。
1.避免嵌套,保持正常流程清晰。
例如有两个if分支都包含return语句,则可以去除冗余的else。 image.png
2.尽量保持正常代码路径为最小缩进。
优先处理错误情况和特殊情况,尽早返回或继续循环来减少嵌套。

错误和异常处理

1.简单的错误
简单的错误指的是仅出现一次的错误,且在其他地方不需要捕获该错误。
优先使用errors.New来创建匿名变量来直接表示简单错误。
如果有格式化的需求,使用fmt.Errorf。
image.png
2.复杂错误:使用错误的Wrap和Unwrap
错误的Wrap实际上提供了一个error嵌套另一个error的能力,从而生成一个error的跟踪链。
在fmt.Errorf中使用:%w关键字来将一个错误关联至错误链中。
image.png
错误判定:判断一个错误是否为特殊错误,使用error.ls
不同于使用==,使用该方法可以判定错误链上的所有错误是否含有特定的错误 image.png
在错误链上获取特定种类的错误,使用errors.AS
image.png 3.Panic
不建议在业务代码中使用panic。
调用函数不包含recover会造成程序崩溃。
若问题可以被屏蔽或解决,建议使用error代替panic。
当程序启动阶段发生不可逆转的错误时,可以在init或main函数中使用panic。
4.recover
recover只能在被的defer的函数中使用。
嵌套无法生效。
只在当前goroutine生效。
defer的语句后进先出。
如果需要更多的上下文信息,可以recover后在log中记录当前的调用栈。
总结:
error尽可能提供简明的上下文信息链,方便定位问题。
panic用于真正异常的情况。
recover生效范围,在当前goroutine的被defer的函数中生效。