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

86 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第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语言

业务服务优化: