这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
本堂课主要内容是高质量编程与性能调优实战,下面主要是我个人听课时的一些笔记
个人笔记
高质量编程
-
什么样的代码才算“高质量”?
- 各种边界条件是否考虑完备
- 异常情况处理,稳定性保证
- 易读易维护
-
编程原则:
-
简单性
以最简单清晰的逻辑写代码
-
可读性
确保代码可以被其他阅读者理解,便于他人对代码进行维护
-
生产力
-
-
那么如何编写高质量的Go代码呢?
-
代码格式
使用
gofmt工具,帮助将代码格式化为官方统一风格使用
goimports,在gofmt的基础上添加了依赖包管理,可以自动增删依赖包的引用,并将依赖包按照字母顺序排序 -
注释
Good code has lots of comments, bad code requires lots of comments. 好的代码有很多注释,坏代码需要很多注释 ——Dave Thomas and Andrew Hunt
-
注释应该解释代码作用,如对外提供的函数需要添加注释来描述它的功能和用途
只有在函数的功能简单而明显时才能省略这些注释,如简单的取值和设值函数
-
注释应该解释实现过程
代码中的一些复杂且不明显的逻辑需要添加注释进行说明,便于理解
-
注释应该解释代码实现原因
这种情境下需要注释来说明这样写代码的原因,适合解释代码的外部因素,提供额外的上下文
-
注释应该解释代码什么情况下会出错
提醒使用者一些潜在的限制条件或者无法处理的情况
-
-
变量命名规范
缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写 例如使用
ServeHTTP而不是ServeHttp使用XMLHTTPRequest或者xmlHTTPRequestpackage命名只由小写字母组成,不包含大写字母和下划线,且不能与标准库同名
-
控制流程
如果两个分支中都包含return语句,则可以去除冗余的else
优先处理错误情况/特殊情况,尽量保持正常代码路径为最小缩进
-
错误和异常处理
优先使用
errors.New来创建匿名变量来直接表示简单错误 如果有格式化的需求,使用fmt.Errorf在
fmt.Errorf中使用: %w关键字来将一个错误关联至错误链中fmt.Errorf("reading srcfiles list: %w",err)错误判定:
判定一个错误是否为特定错误,使用
errors.Is不同于使用==,使用该方法可以判定错误链上的所有错误是否含有特定的错误
在错误链上获取特定种类的错误,使用
errors.As异常处理:
不建议在业务代码中使用panic,因为如果调用函数不包含recover会造成程序崩溃
若问题可以被屏蔽或解决,建议使用error代替panic
只由当程序启动阶段发生不可逆转的错误时,才可以在init或main函数中使用panic
recover:
recover只能在被defer的函数中使用,嵌套无法生效,且只在当前goroutine生效
如果需要更多的上下文信息,可以recover后在log中记录当前的调用栈
-
-
性能优化建议
-
Benchmark
Go语言自身提供的支持基准性测试的benchmark工具
go test -bench=. -benchmem -
Slice内存预分配
切片的自动追加扩容会比较耗时,所以尽量在用
make()初始化切片的同时提供容量信息,这样只有一次内存分配 -
Slice拷贝创建
在已有切片基础上创建切片,不会创建新的底层数组
在原切片较大,且需要在原切片基础上新建小切片时,可以使用
Copy()代替re-slice -
map内存预分配
-
字符串处理
使用
strings.Builder进行字符串拼接,在拼接时不需要重新分配内存(但是+需要重新分配内存) -
空结构体
空结构体
struct{}实例不占据任何的内存空间可作为各种场景下的占位符使用
实现set也可以用这种方法下的map代替(map的value是
struct{}类型) -
atomic包
之前文章中提过,这里不再赘述
-
性能调优实战
主要是介绍了性能分析工具pprof的使用和原理,以及基于pprof,结合案例介绍了实战中如何进行性能调优
pprof是用于可视化和分析性能分析数据的工具
这里是pprof官方的document
参考
- 字节内部课—高质量编程与性能调优实战
- golang pprof 实战