这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记
高质量编程
编程,实现功能是第一目的。在实现功能之余,需要考虑高质量编程,一些编码的规范和性能的优化
简介
编写的代码能够达到正确可靠,简洁清晰的目标可称之为高质量代码。
考虑各种边界情况是否考虑完备;异常情况是否考虑到,是否能保持稳定;是否易读易维护;能简单实现就不复杂地实现
编程原则
简单性;可读性;生产力(关注团队整体工作效率)
编码规范
代码格式
gofmt,goimports
注释
注释应该做的:解释代码作用,解释代码如何做的,解释代码实现的原因,解释代码什么情况会出错
公共符号始终要注释;库中的任何函数必须注释;例外,不需要注释实现接口的方法
代码是最好的注释,注释应该提供的是代码不能提供的上下文信息
命名规范
- 变量名:简洁胜于冗长;缩略词全大写,如HTTP而不是Http;变量距其被使用的地方越远,则需要携带越多的上下文信息,便于任何地方都可以清晰辨认出含义
- 函数名:不携带包名的上下文信息,因为包名和函数名是成对出现的 (包名.函数名);尽量简短;当名为 foo 的包中某个函数返回类型 Foo 时,可以省略类型信息而不致出现歧义;而返回的不是 Foo 类型时,可以在函数名中加入类信息
- 包名:只有小写字母;简短并含有一定的上下文信息;不要与标准库同名;不使用常用变量名作为包名,如标准库中的 bufio 而不是 buf;使用单数而不是复数;谨慎地使用缩写,如 fmt 在不破坏上下文的情况下比 format 更简短
控制流程
错误和异常处理
- 简单错误:简单错误是指仅出现一次的错误,且在其他地方不需要捕获该错误;优先使用 error.New 来创建匿名变量来直接表示简单错误;如果有格式化的需求,使用 fmt.Errorf
- 错误的 Wrap 和 Unwrap:错误的 Wrap 实际上是提供了一个 error 嵌套另一个 error 的能力,从而生成一个 error 的跟踪链;在 fmt.Errorf 中使用 %w 关键字来将一个错误关联至错误链中
- errors.Is,errors.As
- panic。在程序出现无法继续执行下去的情况时尽早抛出 panic 结束无意义的运行
- recover
性能优化建议
性能优化的前提是满足正确可靠,简洁清晰等质量因素;性能优化是综合评估,有时候时间效率跟空间效率可能是对立的
性能测试工具:benchmark
- 预分配:Slice 尽可能在使用 make() 初始化切片时提供容量信息;Map 也提倡尽可能与分配内存,提前分配好空间可以减少内存拷贝和rehash的消耗,建议根据实际需求提前预估好需要的空间
- 字符串拼接,三种方式:"+",strings.Builder,bytes.Buffer,第二种较优
- 使用空结构体本身不占据内存
- atomic包
性能调优
做算法题时会想优化算法,使其执行耗时减少。而实际开发中的优化与算法题有一定区别,它并不一定有明确的边界,限制,需要我们对整条链的理解和我们实际生活适配的场景进行分析。需要定位到应用中性能瓶颈的地方,然后进行相关的优化流程,工具
性能调优原则
要依靠数据不是猜测
要定位最大瓶颈而不是细枝末节
不要过早优化
不要过度优化
性能分析工具 pprof
性能调优案例
业务服务优化
建立服务性能评估手段
分析性能数据定位性能瓶颈
重点优化项改造
优化效果验证
基础库优化
AB实验SDK的优化
分析基础库核心逻辑和性能瓶颈,优化后压测验证,推广业务服务落地验证。验证的步骤通常是所有优化都应经过的
Go 语言优化
编译器&运行时优化:优化内存分配策略;优化编译流程;验证 这种优化的优点是接入简单,任何一个 GO 应用程序都可以使用到,只需调整编译配置,通用性强