这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记。
一.高质量编程 ,编码规范, 性能优化建议。
什么是高质量, 可靠正确,简洁清晰 各种边界条件是否考虑完备,异常情况处理,稳定性保证, 易读易维护,下游代码是否好处理
编程原则
-
简单性
消除多余的复杂性,以简单清晰的逻辑编写代码,不好定位,不好改动
-
可读性
代码是给人看的
编写可维护代码第一步是确保代码可读
-
生产力
团队整体工作效率很重要,用工具统一代码格式。
编码规范
-
代码格式
- gofmt自动格式化代码,官方推荐工具,常见ide都支持
- goimports 自动增删依赖的包引用
-
注释
-
注释应该解释代码作用
-
应该解释代码如何做的
-
代码实现原因
- 适合解释代码的外部因素
- 提供额外上下文
-
什么情况会出错
- 适合解释代码的限制条件
公共符号始终要注释
有一个例外,不需要注释实现接口的方法
好的代码有很多注释,代码是最好的注释,注释应提供代码为表达出的上下文信息
-
-
命名规范
-
variable
- 简洁胜于冗长
- 缩略词全大写,但档期位于变量开头且不需要到处时,使用全小写
- 变量距离其被使用的地方越远,则需要越多的上下文信息
-
function
- 函数名不懈怠报名的上下文信息,因为包名和函数名总是成对出现的
- 函数名尽量简短
- 当包名某个函数和返回类型相同时,可以省略类型信息而 不导致歧义
-
package
- 只由小写字母组成,不包含大写字母和下划线
- 简短并包含一定上下文信息
- 不要与标准库同名
- 尽量不适用常用变量作为包名
- 使用单数而不是复数
- 谨慎的使用缩写
小结:降低阅读理解代码的成本
重点考虑上下文信息,设计简洁清晰的名称
-
-
控制流程
- 避免嵌套
- 尽量保持正常代码路劲为最小缩进
小结:线性原理,避免复杂嵌套分支,故障大多出现在复杂的条件和循环语句中。
-
错误异常处理
-
简单错误:优先使用errors.New
-
错误的Wrap和Unwrap
-
错误判定
- 判定一个错误是否为特定错误,erros.Is
- 再错误链上获取特定种类的错误,使用errors.As
- panic:不见以在业务中使用panic
-
recover
- 只能在被defer的函数中使用
- 嵌套无法生效
- 旨在当前goroutine生效
- defer后进先出
-
小结:error尽可能提供简明的上下文信息链,方便定位问题
panic用于真正异常的情况
recover生效范围,在当goroutine的被的defer的函数中生效
二.性能调优简介
前提:正确可靠,简洁清晰等质量因素
-
如何使用
- 性能表现需要时机数据衡量
- Go语言提供基准性能测试benchmark工具
-
slice预分配内存
- 尽可能在使用make()初始化切片时提供容量信息
- 另一个陷阱:大内存未释放,可用copy替代re-slice,因为如果原底层数组在内存中有引用,得不到释放
-
map预分配内存
-
字符串处理
-
使用strings.Builder,+每次重新分配内存,其他两个有内存扩容策略,Builder效率好点
预先分配内存效率会更高
-
-
空结构体
-
atomic包
- 性能比加锁高 !
小结:
- 避免常见性能陷阱
- 不要一味追求程序性能
- 越高级的性能优化手段越容易出现问题
- 在满足正确可靠,简洁清晰的质量要求的前提下提高程序性能
性能分析工具pprof
-
性能调优原则
- 依靠数据不是猜测
- 定位最大瓶颈不是细枝末节
- 不要过早优化
- 不要过度优化
-
浏览器查看指标
可以在go tool pprof 后加上-http=:8080 再加上”httpxxx"可以可视化
-
火焰图
- 从上到下表示调用顺序
- 每一块代表一个函数,越长代表占用cpu时间更长
- 火焰图是动态的,支持点击块进行分析
-
采样过程和原理
三.性能调优案例
-
业务服务优化
- 建立服务性能评估手段
- 重点优化项改造
- 优化效果验证
- 进一步优化,服务整体链路分析
-
基础库优化
-
AB实验SDK的优化
- 基础库核心逻辑和性能瓶颈
- 内部压测验证
- 推广业务服务落地验证
-
-
Go语言优化
- 编译器&运行时优化
总结
性能调优原则
- 要依靠数据不是猜测
性能分析工具pprof
性能调优
- 保证正确性
- 定位主要瓶颈