高质量编程通常指编写可维护、可扩展、可读性好、可测试和可靠的代码。在实践中,高质量编程的标准可能因编程语言、项目需求、团队规模和其他因素而有所不同。
代码可读性
简单性
消除“多余的复杂性”,防止出现无法更改的复杂逻辑代码。
可读性
代码可维护的前提是代码可读
生产力
团队整体工作的效率与代码质量正相关
官方工具
使用gofmt与goimports进行代码的格式化
编码规范 - 注释
注释应该做到的:
- 解释代码作用
- 解释代码是如何实现的
- 注释代码书写原因:主要是一些脱离当前代码的外部因素
- 解释代码什么情况下会出错
编码规范 - 命名规范
变量
- 仅限于循环内部的变量可以使用单字母命名
- 函数名不携带包名的上下文,尽量简单
- 当函数名与返回数据类型相同时可以省略类型信息
- 包名只由小写字母组成,简单包含一些上下文信息
- 不适用常用变量名
- 使用单数而不是复数
- 谨慎使用缩写
编码规范 - 流程控制
- 尽量保持代码为最小缩进
- 遵循线性处理原则
编码规范 - 错误和异常处理
- 简单错误:errors.New创建匿名变量
-
复杂错误:错误的Warp机制
- 错误的warp实际上是提供了一个error嵌套另一个error的能力,从而生成一个error的跟踪链
- 在fmt.Errorf中使用
%w关键字将一个错误关联至错误链
- 错误判定:使用error.As
- panic:尽量少的使用panic
- recover:只能在defer使用,不能嵌套,只在当前goroutine生效,一般用于打印调用栈复现错误
性能优化
性能测试
使用go test -bench=. -benchmem进行性能测试
优化建议
slice
- 尽量使用预分配(slice本质是数组)
- 在已有切片的基础上创建切片,不会创建新的切片,如果原切片>新切片,会导致内存浪费
map
- 使用预分配
string
- 使用strings.Builder或strings.Buffer代替直接使用+,可以减少内存浪费
- 使用buf.Grow与builder.grow,提前分派内存
空结构体
- 空结构体不占用任何空间,可以作为占位符
atomic包
使用atomic包来维护多线程变量,atomic通过硬件实现,效率更高,使用atomic.Value承载interface