高质量编程简介及编码规范(2) ----- 错误和异常处理
简单错误 & 简单的错误指的是仅出现一次的错误,且在其他地方不需要捕获该错误 & 优先使用 errors.New 来创建匿名变量来直接表示简单错误 & 如果有格式化的需求,使用 fmt.Errorf
----- 错误的Warp 和 Unwarp & 对于复杂的错误,有时候并不能简单描述,错误的 Wrap(包装) 提供了一个error嵌套另一个error的能力,生成一个error的 跟踪链,同时结合错误的判定方法来确认调用链中是否有关注的错误出现 & 在 fmt.Errorf 中使用 %w 关键字来将一个错误关联至其错误链中
----- 错误判定 & 判定一个错误是否为特定错误,使用 errors.Is & 不同于直接使用 == ,使用该方法可以判断错误链上的所有错误是否含有特定的错误
& 在错误链上获取特定种类的错误,使用 errors.As
----- panic & 不建议在业务代码中使用 panic & 调用函数不包含 recover 会造成程序崩溃 & 若问题可以被屏蔽或解决,建议使用 error 代替 panic & 当程序启动阶段发生不可逆转的错误时,可以在 init 或 main 函数中使用 panic
-----recover & recover 只能在被 defer 的函数中去使用 & 嵌套无法生效 & 只在当前 goroutine 生效 & defer 的语句时后进先出
& 若需要获取更多的上下文信息,可以 recover 后在 log 中记录当前的调用栈
------小结 & error 尽可能提供简明的上下文信息链,方便定位问题 & panic 用于真正异常的情况 & recover 生效范围:在当前 goroutine 的被 defer 的函数中生效
编码规范: 性能优化建议 -----Slice 预分配内存 & 尽可能在使用 make() 初始化切片时提供容量信息
切片本质是一个数组片段的描述
* 包括数组指针
* 片段的长度
* 片段的容量(不改变内存分配情况下的最大长度)
切片操作并不复制切片指向的元素
创建一个新的切片会复用原来切片的底层数组
注意:在已有切片基础上创建切片,不会创建新的底层数组,这可能会导致内存泄漏发生,此时可 copy 代替 re-slice
-----map 预分配内存 分析: & 不断向 map 中添加元素的操作会触发 map 的扩容 & 提前分配好空间可以减少内存拷贝和 Rehash 的消耗 & 建议根据实际需求提前预估好需要的空间 -----字符串 strings.Builder 拼接 & 建议使用 strings.Builder 拼接字符串 & 使用 + 拼接性能最差, strings.Builder,bytes.Buffer 相近,strings.Builder 更快 分析: & 字符串在 Go 语言中是不可变类型,占用内存大小是固定的 & 使用 + 每次都会重新分配内存 & string.Builder,bytes.Buffer 底层都是 []byte 数组 & 内存扩容策略,不需要每次拼接重新分配内存 ----- 空结构体 & 使用空结构体节省内存 & 空结构体 struct{} 实例不占据任何的内存空间 & 可作为各种场景下的占位符使用 -----总结 高质量的代码能够完成功能,但是在大规模程序部署的场景,仅仅支持正常功能还不够,我们还要尽可能的提升性能,节省资源成本!