这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记
高质量编程
正确可靠,简洁清晰
边界条件、异常处理,易读易维护
通用原则:
- 简单性:简单清晰的逻辑,消除多余的复杂性
- 可读性,便与维护
- 生产力:团队的整体效率
在go中
代码格式:gofmt自动格式化,或者goimports,可以排序依赖包
注释:解释代码的作用,如何做的,原因,什么情况会出错。考虑别人阅读时会要求什么信息
作用注释:适合注释公告符号,
如何做的注释:实现过程,有必要才加,
为什么这么写:根据上下文推断不出来的情况
限制条件是什么
不需要注释实现接口的方法,不需要说明在哪里实现
变量命名
简洁胜于冗长
缩略词全大写,但位于开头且不需导出,使用全小写。ServerHTTP,xmlHTTPRequest
变量名距离使用处远时,应携带更多信息。
提供给外部的时候变量本身信息应有
函数名:函数名与包成对出现,不用带包名的上下文,尽量简短。但如果函数名与包名不和,可以带包相关信息。
包名:只能小写,不包含大写、下划线。包含上下文信息,使用单数,不用常量名。
控制流程:优先处理每一种错误,最后一步就是正常的功能。实际中循环与控制流程很容易出错
fmt.Errorf : %w错误跟踪链
erros.As
panic:不建议在业务中使用,
recover:在defer中,只在当前goroutine
defer后进先出
编码规范
性能调优实战
benchmark工具
go test -bench =. -benchmen
slice:创建时预分配内存,因为容量不够时会创建一个两倍大小的新数组。
创建新切片复用底层数组,当用到原始数组中一小部分的话,没用到的就得不到释放。使用copy代替。
map预分配内存,因为增加元素会导致map扩容
字符串处理:使用string.Builder.
+性能最差,strings.Builder,bytes.Buffer相近
因为go中字符串不可变,使用+会重新分配新字符的内存
strings.Builder,bytes.Buffer底层都是[]byte 数组
性能优化:空结构体,不占用任何内存
atomic包,比加锁性能好。锁属于系统调用,atomic硬件实现。
性能优化:
依靠数据,定位瓶颈,不要过早优化,不要过度优化
pprof:
cpu采集
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=60"
top:
flat当前函数本身执行耗时
flat%比例
sum%上面所有行的总和
cum:本身和调用其他函数的总耗时
flat=cum,没有调用别的函数
flat=0,只调用其他函数
list ***,入list Eat
web
内存:Head
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
goroutine:
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"
mutex:
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"
block:
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"
过滤节点:采样到了好几个,之展示耗时大的
在终端go tool pprof "http://localhost:6060/debug/pprof/block"可以看采样到的,同时显示了过滤条件,cum <= 1.41s。可以在首页点block,debug/pprof首页。
展示方式:top,graph,火焰图flamegraph
分析:网页,可是化终端
pprof采样过程和原理:
操作系统每10ms向进程发送一次SIGPROF信号,进程收到这个信号会记录调用堆栈,每100ms读取记录的调用栈并写入输出流。
heap:通过内存分配器在堆上分配和释放的内存
优化方面:业务服务、基础库、go语言
业务服务优化: