这是我参与「第三届青训营 -后端场」笔记创作活动的的第 3 篇笔记 ~
高质量
边界条件考虑完备、处理异常情况、易读易维护
代码格式
gofmt
或者goimports
注释
提供额外信息
命名规范
简洁
(包名)
缩略词全大写,但是当位于变量开头且不需要导出时,全小写
(函数)
不携带包名的上下文信息,因为包名和函数名总是成对出现
尽量简短
(包package)
只由小写字母组成,不含大写字母、下划线
不要和标准库同名
控制流程
避免嵌套,保持正常流程清晰
保持正常代码路径为最小路径
线性原理
优先处理错误情况/特殊情况,尽早返回或继续循环来减少嵌套
成功的退出条件 return nil
最后一行返回一个错误,需要追溯到匹配的左括号,才能了解何时会触发错误
错误和异常处理
简单错误(只出现一次的错误,其他地方不需要捕获该错误)
errors.New创建匿名变量
获取特定类型的错误
errors.AS
recover
只能在被defer的函数中使用
defer语句
函数返回前调用
多个defer语句是后进先出
嵌套无法生效,只在目前goroutine生效
后进先出
panic不建议在业务代码中使用,而是用于真正异常的情况
性能优化
go自带的支持基准性能测试的 benchmark
go test -bench =. -benchmem
slice预分配内存
尽可能在使用 make() 初始化切片时,提供容量信息
(减少分配次数)
切片本质是对数组片段的描述
map预分配内存
增加元素导致扩容
提前分配空间,减少内存拷贝和rehash的消耗
strings.Builder
使用+拼接性能最差
字符串在go中占用内存大小固定
使用+每次都会重新分配内存
空结构体,不占内存,当占位符
struct()
使用 atonic包
实战
性能调优原则:依靠数据而不是猜测、定位最大瓶颈而不是细枝末节
性能分析工具pprof
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
web命令,调用关系可视化
heap 堆内存
执行命令 go tool pprof -http=:8080
"http://localhost:6060/debug/pprof/heap"
火焰图
从上到下表示调用顺序
每个块代表一个函数,越长代表占用时间越长
业务服务优化
系统部署的简单示意图,客户端请求经过网关转发,由不同的业务服务处理,可能依赖其他服务,或存储、消息队列等组件
service B 被A 依赖,同时也依赖存储和 D
核心:发现服务性能的瓶颈
json解析:数据变更时再重新解析json, 可以减少cpu资源占用
高并发场景下的性能:火焰图对比
监控组件的数据上报说同步请求,造成阻塞
改成异布上报的机制提升性能
在熟悉服务的整体部署情况后,可以针对更具体的接口链路进行 调优,例如是否存在重复调用、是否更小的结果数据集就能满足需求、接口是否需要实时数据、是否能在调用方进行缓存,减轻调用压力