这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天。
今天老师讲了Go高质量编程和性能调优方面的内容,在实际的应用中比较重要,记录了一些重要的知识点。
高质量编程
最终的目的是编写简洁清晰的代码,要考虑以下几个属性。
高质量: 正确可靠、简洁清晰
简单性:用简单清晰的逻辑来写代码(防止后面的人不敢修改代码,难以维护)。
可读性: 写的代码人要看得懂。
生产力:考虑团队其他人阅读代码的难度。
如何编写高质量Go代码:
代码格式:用gofmt自动格式化代码。
注释:写清楚作用,解释实现原因和出错原因 ,注释要提供代码未表达的上下文信息。
命名规范:降低阅读成本,考虑上下文信息。
错误和异常处理:
1.简单错误:用errors.New()表示简单错误,需格式化用fmt.Errorf,尽可能提供简明的上下文信息。
2.panic:不建议在业务代码中使用,在启动阶段使用,如init,或main函数中使用,用于真正异常的情况。
3.recover:只能在被defer的函数中使用,只在当前goroutine生效。
性能优化
性能优化建议:
Slice:尽可能在使用make()初始化切片时提供容量信息。在已有切片基础上创建切片,不会创建新底层数组,所以当原切片很大,又在原切片基础上创建小切片就会让原来的大底层数组得不到释放,可用copy代替re-slice。
Map:预分配内存,和Slice类似
字符串处理:使用strings.Builder进行字符串拼接(bytes.Buffer性能略逊,+性能最差)。
strings.Builder,bytes.Buffer底层使用[]byte数组,不需要每次重新分配内存,+需要重新分配内存。
strings.Builder性能略好的原因是直接将[]byte转换成字符串返回,而bytes.Buffer转换时重新申请了一片空间
再优化:为strings.Builder预分配内存
空间优化:
空结构体:空结构体struct实例不占据任何内存空间,如使用map时初始值设为struct{}{}
atomic包:性能会比加锁高(和原子操作差不多,效果和锁类似)