这是我参与「第五届青训营 」笔记创作活动的第3天
1. 错误和异常处理
简单错误:
- 简单错误指的是仅出现一次的错误,且在其他地方不需要捕获该错误
- 优先使用errors.New来创建匿名变量来直接表示简单错误
- 如果有格式化的需求,使用fmt.Errorf
错误的Wrap和Unwrap:
- 错误的Wrap实际上是提供了一个error嵌套另一个error的能力,从而生成了一个error的跟踪链
- 在fmt.Errorf中使用:%w 关键字来将一个错误关联至错误链中
错误判定:
- 判定一个错误是否为特定错误,使用errors.Is
- 不同于==,使用该方法可以判定错误链上的所有错误是否含有特定的错误
- 在错误链上获取特定种类的错误,使用errors.As
panic:
recover:
- recover只能在被defer的函数中使用
- 嵌套无法生效
- 只在当前goroutine生效
- defer的语句是后进先出
- 如果需要更多的上下文信息,可以recover后在log中记录当前的调用栈
总结:
- error尽可能提供简明的上下文信息链,方便定位问题
- panic用于真正异常的情况
- recover生效范围,在当前goroutine的被defer的函数中生效
2. 性能优化
建议:
slice,map使用时设置大小,可以减少扩容的开销;
字符串使用string.builder,拼接会更快;
atomic包:
- 锁的实现是通过操作系统来实现,属于系统调用
- atomic操作是通过硬件实现,效率比锁高
- sync.Mutex应该用来保护一段逻辑,不仅仅用于保护一个变量
- 对于非数值操作,可以使用atomic.Value,能承载一个interface{}
性能调优原则:
- 要依靠数据不是猜测
- 要定位最大瓶颈而不是细枝末节
- 不要过早优化
- 不要过度优化
性能分析工具pprof: