这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
1.编程原则:
- 简单性:“消除多余的复杂性”,以简单清晰的逻辑编写代码·不理解的代码无法修复改进
- 可读性: 代码是写给人看的,而不是机器,编写可维护代码的第一步是确保代码可读
- 生产力:团队整体工作效率非常重要
2.注释:
- 代码是最好的注释
- 注释应该提供代码未表达出的上下文信息
3.控制流程
- 线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支
- 正常流程代码沿着屏幕向下移动
- 提升代码可维护性和可读性
- 故障问题大多出现在复杂的条件语句和循环语句中
4.错误和异常处理
- error尽可能提供简明的上下文信息链,方便定位问题
- panic用于真正异常的情况
- recover生效范围,在当前goroutine的被defer的函数中生效
5.性能优化
5.1 BenchMark结果
5.2 优化
- slice 预分配内存
- 大内存未释放:可用copy代替re-slice
func GetLastBySlice(origin []int)[]int{
return origin[len(origin)-2:]
}
func GetLastByCopy(origin []int)[]int{
result := make([]int,2)
copy(result,origin[len(origin)-2:])
return result
}
- map 预分配内存
- 字符串拼接,支持预分配 builder.Grow(), buf.Grow()
# 使用+拼接性能最差,strings.Builder,bytes.Buffer相近,strings.Buffer更快
# 字符串在Go语言中是不可变类型,占用内存大小是固定的使用,每次都会重新分配内存
# strings.Builder,bytes.Buffer 底层都是[]byte数组,内存扩容策略,不需要每次拼接重新分配内存
- 使用空结构体节省内存
- atomic包
# 锁的实现是通过操作系统来实现,属于系统
# 调用atomic 操作是通过硬件实现,效率比锁高
# sync.Mutex应该用来保护一段逻辑,不仅仅用于保护一个变量
# 对于非数值操作,可以使用atomic.Value,能承载一个 interfacet