高质量编程与性能调优 | 青训营笔记

125 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第二篇笔记。

高质量编程与性能调优

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 性能调优案例

通过案例了解了在实际项目中整个调优过程和调优方向,任何精确定位优化位置。