这是我参与「第五届青训营 」伴学笔记创作活动的第 3天,今天学习了Go高质量代码规范以及性能调优的知识下面是我的笔记。
Go高质量编程及性能调优
1、高质量编程
1.1、高质量编程的意义
编写的代码能够正确可靠,简洁清晰
- 简单性:消除多余的复杂性,以简单清晰的逻辑写代码,不理解的代码无法修复改进
- 可读性:代码是写给人看的,不要写的太花
- 生产力:注重团队工作效率
1.2、编码规范
- 注意合理编写注释
- 注释应该解释代码作用
- 注释应该解释代码实现的原因
- 注释应该解释代码什么时候可能出错
- 公共符号始终要注释
- 包中声明的公共符号,变量,常量,函数,结构体,都要注释
- 任何不明显不简短的公共功能,要注释。
- 无论长度或者复杂的程度,对库中的任何函数都要进行注释。
- 对实现接口的方法不需要注释,而是要注释出方法究竟实现了什么功能。
- 命名规范
- variable变量:简洁为佳,注意达意,函数参数要做到英文不要过于笼统,例如对于 Time类对象,可以分别命名为,deadline,beginTime,nowTime,等等而不是t。
- function函数:不携带包的信息,因为与包是成对出现的,不要将函数名命名与关键字类似,例如http包中,命名func不需要再命名成serverhttp()这种,直接server()就行
- package:只有小写字母完成,简短包含上下文,不要与标准库重名,不使用复数而是单数,缩写谨慎,
- 控制流程
- 避免分支嵌套,尽量减少else。
- 提升可读性,拒绝无脑多重循环和条件语句
- 错误和异常的处理
- 简单错误使用errors.New即可,力求简洁
- 复杂错误 使用fmt.Errorf(format string,err error)格式化输出。
- 错误判定 errors.Is ,判断是否是某种错误(可自定义)
- 错误判定 errors.As,取出错误链中的错误
- 不建议在业务中使用panic(恐慌),当程序启动阶段发生不可逆转的错误,可以在init(),main()函数中panic
- recover:如果需要更多上下文信息,可以在recover后再log中记录当前的调用栈,recover仅仅在当前的goroutine被defer的函数中。
2、性能测试与优化
2.1、benchmark测试
- 主要格式要求:
- Benchmark打头
- 不能有返回值
- 文件以_test.go结尾
// 文中全局有一个StrData变量,是一个200长度的字符串slice
// 间接应用“+”号拼接
func BenchmarkStringsAdd(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
var s string
for _, v := range StrData {
s += v
}
}
b.StopTimer()
}
2.2、优化策略
-
slice性能优化
预分配容量在已有切片基础上创建切片,注意大内存未释放的陷阱。使用copy代替re-slice
-
map性能优化
预分配内存
-
字符串拼接处理
使用 string.Builder
-
使用空结构体
-
需要原子计数时使用atomic原子工具包,而不是一味使用锁,因为锁是通过操作系统实现的,比较慢,原子计数通过硬件实现,比较简单。
2.3、性能调优工具pprof
真正分析时常用4种
-
CPU Profiling:CPU 分析,按照一定的频率采集所监听的应用程序 CPU(含寄存器)的使用情况,可确定应用程序在主动消耗 CPU 周期时花费时间的位置
-
Memory Profiling:内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前和历史内存使用情况,以及检查内存泄漏。
-
Block Profiling:阻塞分析,记录 goroutine 阻塞等待同步(包括定时器通道)的位置。
-
Mutex Profiling:互斥锁分析,报告互斥锁的竞争情况。