这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记
良好的的代码习惯能体现出程序员的内功。
编码规范:
注释
-
解释代码作用
- 所有的公共符号都需要注释
- 无论长度和复杂程度如何,库中任何函数都必须进行注释
-
解释代码如何做
- 注释实现过程
-
实现的原因
- 解释代码的外部因素
- 提供额外上下文
-
什么情况会出错
- 解释代码的限制条件
代码是最好的注释,注释应该提供代码未表达的上下文,提供额外的有效信息。
命名规范
- 简洁
- 缩略词全大写,处于变量开头且不需要导出,使用全小写
- 变量距离其被使用的地方越远,则需要更多上下文信息,使得容易被辨认其含义
- package:只由小写字母组成。不包含大写字母和下划线的字符。尽量使用单数。
控制流程
- 避免嵌套,保持正常流程流畅
- 尽量保持正常代码路径为最小缩进
- 线性原则,处理流程尽量直线,避免复杂的嵌套分支
- 正常代码沿着屏幕向下移动
- 提高可维护性和可读性
- 故障问题大多出现在复杂的条件语句和循环语句中
错误和异常处理
- 优先使用 errors.New 来创建匿名变量来直接表示简单错误
- 如果有格式化需求,使用 fmt.Errorf
性能优化建议
- 正确可靠、简洁清晰
- 综合评估空间效率与时间效率
Benchmark
Go 语言提供支持基准性能测试的工具 benchmark
go test -bench=. -benchmem
-
尽可能在使用make() 初始化切片时提供容量信息
- 切片本质是一个数组片段的描述:数组指针、片段的长度、片段的容量
-
map 预分配内存
- 不断向map添加元素的操作会触发map的扩容
- 提前分配好空间可以减少内存拷贝和Rehash的消耗
- 根据实际提前评估好需要的空间
- 字符串在Go语言中是不可变类型,占用内存大小固定,使用 + 每次都会重新分配内存,而
strings.Builder, bytes.Buffer底层都是 byte[]数组,不需要每次重新分配内存
- 使用空结构体节省内存
- 多线程开发中使用 atomic 包:锁的实现通过操作系统实现,属于系统调用。 atomic 操作通过硬件实现,效率比锁高。锁 sync.Mutex 应该用来保护一段逻辑,不仅仅用于保护一个变量
总结:
- 避免性能陷阱
- 普通应用代码,不用一味追求性能
- 越高级性能优化手段越容易出问题
- 满足正确可靠、简洁清晰的质量要求下提高性能