这是我参与「第三届青训营 -后端场」笔记创作活动的的第二篇笔记。
高质量编程与性能调优
0. 前置问题
如何更简洁清晰的编写代码
常用Go语言程序优化手段
熟悉Go程序性能分析工具
了解工程中性能优化的原则和流程
01. 高质量编程
什么高质量:正确、可靠、简洁
1.各种边界条件是否考虑完备(正确)
2.异常情况处理,稳定性保证(可靠)
2.易读易维护(简洁)
1.1 编程原则
1.简单性(简单清晰,消除多余的复杂)
2.可读性(易读易维护)
3.生产力(团队配合效率)
1.2 编码规范
1.2.1 代码格式
使用gofmt自动格式化代码,能自动格式化go语言代码为官方统一风格 goimports,自动增删依赖包的引用、将依赖包按字母排序并分类
1.2.2 注释
注释:
1.解释代码作用
2.解释代码如何做的
3.解释代码实现的原因
4.解释代码在什么情况下会出错
1.2.3 命名规范
1.简洁
2.缩略词全大写,但当其位与变量开头不需要导出时,全小写
3.变量距离其被使用的地方越远,则需要携带更多上下文信息
(自定义包名:只由小写字母组成。不包含大写和下划线等,和标准库不重名)
1.2.4 控制流程
1.避免条件判断嵌套
2.尽量保持正常代码路径位最小缩进
1.2.5 错误和异常处理
1.简单错误:优先使用errors.New来创建匿名变量
2.复杂错误:Wrap和Unwrap
3.错误判断
errors.Is是否为特定错误
errors.As错误链中取出特定种类错误
panic用于真正异常,出现了程序无法执行或者执行了也没有意义的异常
recover:注意只能被defer的函数中使用,嵌套无法生效,只在当前goroutine生效, defer的语句是后进先出
1.3 性能优化建议
1.3.1 Benchmark
性能表现需要实际数据衡量
go语言提供了支持基准性能测试的工具benchmark
1.3.2 Slice预分配内存
尽可能在使用make()初始化切片时提供容量信息 之所以slice预分配内存可以优化性能,是因为slice的本质是一个数组片断描述。其在底层实现时,对于自身容量不足时需要进行扩容,但是其不是本身进行扩容,而是创建了一个比原先容量更大的新slice,并将内容进行值拷贝。这样的反复操作会影响程序的执行效率。
slice中存在的陷阱:大内存未释放问题
原因:在已有切片基础上创建切片,不会创建新底层数组
解决方法: 使用copy代替re-slice(用新建立切片确定新切片容量,通过值拷贝创建新切片)
1.3.3 map预分配内存
原因和之前slice的类似不在赘述
1.3.4 字符串处理
对于拼接操作建议使用strings.Builder和bytes.Buffer,直接用+进行字符串拼接性能最差
原因:
1.go语言中string是不可变类型
2.使用+每次都需要重新分配内存
3.strings.Builder和bytes.Buffer底层都是[]byte数值,都有扩容策略,不需要每次都重新分配内存
1.3.5 空结构体
使用空结构体的原因是因为空结构体实例不占任何内存空间
02.性能调优实战
2.1性能优化原则
1.依靠数据而不是猜测
2.定位最大瓶颈
3.不要过早优化
4.不要过度优化
2.2 性能分析工具 pprof
通过项目熟悉和了解了pprof工具
2.3 性能调优案例
通过案例了解了在实际项目中整个调优过程和调优方向,任何精确定位优化位置。