这是我参与【第五届青训营】伴学笔记创作活动的第三天,此篇概述一下在青训营学习的go语言编程的编码规范以及性能优化方法。
高质量编程简介及编码规范
-
编程原则:简单性、可读性、生产力(团队整体生产效率)
-
如何编写高质量的 go 代码
-
代码格式(推荐使用 gofmt 自动格式化代码)
-
注释
- 范围:包中的公共符号、不简单不明显的功能、库中的所有函数
- 功能:解释代码作用、解释如何实现代码、代码实现的原因、什么情况会出错
-
命名规范
- 核心目标是降低阅读理解代码的成本
- 重点考虑上下文的信息,设计简洁清晰的名称
-
控制流程
- 避免嵌套,保持正常流程清晰
- 尽量保持正常代码路径为最小缩进
-
错误和异常处理
-
简单错误:errors.New() ,如果有格式化需求,使用 fmt.Errorf()
-
错误的Wrap和Unwrap:错误的 Wrap 实际上提供一个 error 嵌套另一个 error 的能力,从而生成一个 error 的跟踪链;在 fmt.Errorf中使用 %w 关键字将一个错误关联至错误链中
list, _, err := c.GetBytes(chane.Subkey(a.actionID, "srcfiles")) if err != nil { return fmt.Errorf("reading srcfiles list: %w", err) } -
错误判定:判定一个错误是否为特定错误,使用 errors.ls(err, errtype) , 可判错误链;
在错误链上获取特定种类的错误,使用 errors.As(err, &pathError)
-
panic:当程序启动阶段发生不可逆转的错误时才建议使用
-
recover生效范围: 在当前 goroutine 的被 defer 的函数中生效
-
-
性能优化指南
-
基准性能测试工具 benchmark
// this.go func Fib(n int) int { if n < 2 { return n } return Fib(n-1) + Fib(n-2) } // this_test.go func BenchmarkFib10(b *testing.B) { for n := 0; n < b.N; n++ { Fib(10) } } -
slice 预分配内存:尽可能在使用 make() 初始化切片时提供容量信息
-
copy 解决新建小切片原底层大数组在内存中有引用,得不到释放的问题
// 原切片方法 func GetBySlice(origin []int) []int { return origin[len(orgin)-2:] } // copy 优化措施 func GetByCopy(orgin []int) []int { result := make([]int, 2) copy(result, orgin[len(orgin)-2:]) return result } -
map 预分配内存:提前预估号需要的空间
-
字符串处理:使用 strings.Builder
-
空结构体节省内存,可当 set 使用, 如 map[int] struct{}