课程主要分为两个部分,分别是高质量编程和性能调优实战。其中高质量编程多是一些指导性原则,辅以一些示例进行讲解,课程PPT以及导学链接中已经总结得很清晰完善,本篇笔记仅将其中总结性内容以及个人不太熟悉的点列出,不详细讲解每一个细节。
本堂课重点内容:
-
高质量编程
- 高质量编程简介
- 编码规范
- 性能优化建议
-
性能调优实战
- 性能调优简介
- 性能分析工具
- pprof实战
- 性能调优案例
高质量编程
编码规范
-
代码格式
使用gofmt格式化代码,使用goimports工具进行包导入管理(可以自动导入包,去除不适用的包,并按字典序排列,节省时间)
-
注释
- 代码是最好的注释
- 注释应该提供代码未表达出的上下文信息
-
命名规范
- 核心目标是降低阅读理解代码的成本
- 重点考虑上下文信息,设计简洁清晰的名称
-
控制流程
- 线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支
- 正常流程代码沿着屏幕向下移动
- 提升代码可维护性和可读性
- 故障问题多出在复杂的循环语句和条件语句中
-
错误和异常处理
- error尽可能提供简明的上下文信息链,方便定位问题
- panic用于真正异常的情况
- recover生效范围,在当前goroutine的被defer函数中生效
关于编码规范其实很多点都需要在实际的开发过程中去体会规范为什么这么设计以及一些具体的Best Practice是如何应用的,课堂上已经总结了不少,这里推荐阅读Go代码Review建议,它可以看作effective go的一个补充。下面我列出一些review建议中比较简单实用但是可能一开始不会注意到的内容
- 用完整的句子写注释方便自动化展示,句子开头为所注释的东西,多句的话第一句作为摘要
- 不要引用其他包的内存(防御式编程)
- 使用
crypto/rand替代math/rand,更加安全 - 错误信息不大写,不要句号,因为错误信息一般都被包括在上下文中
- 接口放在使用方的package中而不是实现方的package,简单来说在接口只有在被使用的地方才定义
- 行的长度应该根据语义而定,不要死守80字符的“规矩”,现在的显示设备已经很先进了,但是一样要避免过长的行
- go中返回值可以有名字,但是要注意不要添加冗余的名字,例如
err error就毫无意义,如果有多个同类型返回值加个名字会好很多 - 不要用
this,me,self给某个类型方法的接收方对象命名(就像这样func (this Hello) hello())
性能优化建议
- 使用Benchmark来衡量性能表现
- Slice预分配内存以减少内存申请,提高运行速度
- Slice使用copy替代re-slice来减少内存占用,节省内存空间
- Map预分配内存
- 字符串处理使用strings.Builder
- 空结构体节约内存,利用其语义特征,同时不耗费资源(利用map实现set)
- atomic包原子化操作提高性能
上面提到的许多建议在这本Go语言高性能编程中都有所涉及,感兴趣可以仔细阅读。
性能调优实战
课程中的讲解示例其实是基于下面这篇博客做的,所以如果课上没有跟着老师做下来的话课后可以看一遍这个博客,博客中讲的很详细适合实操。
pprof是用于可视化和分析性能,分析数据的工具,能够告知程序在什么地方耗费了多少CPU,多少内存等实际的数据指标。
💡 注意这里很多同学运行此项目都出了一些问题,下面给出解决方案。
pprof可以采样程序运行时的CPU、堆内存、goroutine、锁竞争、阻塞调用和系统线程等的使用数据,同时通过列表、调用图、火焰图、源码以及反汇编等视图展示采集到的性能指标。
首先直接从GitHub中clone下来的项目是没有go.mod文件的,而go1.18强制使用module来管理项目,所以需要我们自己生成go.mod文件,具体运行以下命令
bash
复制代码
$ go mod init github.com/wolfogre/go-pprof-practice
$ go mod tidy
会生成如下的go.mod文件
go
复制代码
module github.com/wolfogre/go-pprof-practice
go 1.18
可以看到是没有外部依赖的。
其次需要注意这里的module名字不能修改,只能是github.com/wolfogre/go-pprof-practice,如果你使用了其他的名字,例如go-pprof-practice,则会生成这样的go.mod文件
go
复制代码
module go-pprof-practice
go 1.18
require github.com/wolfogre/go-pprof-practice v0.0.0-20190402114113-8ce266a210ee
虽然程序也能运行,但是依赖的却是GitHub上的仓库(go mod tidy会将这个包拉下来存到你的gopath里面),你修改你本地tiger.go文件中的内容,main函数的运行结果是不会变的。
课程中还讲解了实际业务性能调优的案例,不过我还未接触过相关实际业务,对此方面完全没有概念,所以仅作了解。