第三节课【高质量编程与性能调优实战】
这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记
高质量编程
代码格式
使用编译器自动格式化
注释
一定要记得对代码进行注释
公共符号:变量、常量、函数以及结构都需要添加注释
私有的功能则看情况注释
-
注释应该做的
- 注释应该解释代码作用
- 注释应该解释代码如何做的
- 注释应该解释代码实现的原因
- 注释应该解释代码什么情况会出错
命名规范
variable
简洁胜于冗长
缩略词需要全大写,但如果其位于变量开头且不需要导出时,使用全小写
变量距离被使用的地方越远则需携带更多上下文信息
function
不需要携带包名信息(因为包名和函数名总是成对出现)
尽量简短
package
只由小写字母组成,且不包含下划线
简短并包含一定上下文信息
不与标准库同名
使用单数而不是复数
性能优化
slice预分配内存
在预知slice最终大小的时候,尽可能在使用make初始化切片时提供容量信息
slice内存陷阱
当需要切片中的切片时,尽量新建一个切片后使用copy函数进行复制,而不是直接返回切片的切片。
原因:当以切片创建切片时,其实并没有创建新的底层数组,新的切片只是对原来切片的引用,如果只需要新的切片,则由于旧的切片一直被引用,会有很大一部分内存空间将会被浪费
map预分配内存
同切片类似,在预知map最终大小的时候,也可以在make初始化时预分配内存
字符串处理
使用strings.Builder拼接字符串,要优于使用 “+” 和bytes.Buffer
拼接时:
“+” 每次拼接字符串都需要重新分配内存,strings.Builder和bytes.Buffer底层都是[]byte数组,有内存扩容策略
转化为字符串时:
bytes.Buffer转化为字符串时重新申请了一块空间,而strings.Builder直接将[]byte类型转化为string类型
使用空结构体节省内存
如:实现set
可用map代替,键为需要的变量类型,值为空结构体
使用atomic包
锁的实现是通过操作系统来实现,属于系统调用
atomic操作则通过硬件实现,效率比锁高
性能调优
排查工具
运行课程代码后,可进入localhost查看性能指标
运行时间
终端输入:go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
可再输入:
top:查看占用资源最多的函数
list + (函数名): 查找代码行
web :查看关系可视化图(须先安装Graphviz,下载地址:Download | Graphviz)
堆内存
终端输入:go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap" 可直接进入可视化网页
协程
终端输入:go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"
锁
终端输入:go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"
阻塞
终端输入:go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"