高质量编程
- 边界条件
- 异常情况处理,稳定性表示
- 易读易维护
编程原则
- 简单性
- 消除多余的复杂性
- 不理解的代码无法修复改进
- 可读性
- 编写可维护代码的第一步是确保代码可读
- 生产力
- 团队整体工作效率
编程规范
- 代码格式 (推荐使用 gofmt 自动格式化代码)
有关gofmt的更多信息,请参见“go doc cmd/gofmt”。
用法:
gofmt [flags] [path ...]
The flags are:
-cpuprofile string
将CPU配置文件写入此文件
-d
不将重新格式化的源打印到标准输出。
如果一个文件的格式与gofmt的不同,则将差异部分打印到标准输出。
-e
打印所有(包括虚假)错误。
-l
不将格式化的源打印到标准输出。
如果文件的格式与 gofmt 不同,则将其名称打印到标准输出。
-r rule(string)
在重新格式化之前,对源应用重写规则(例如,'a[b:len(a)] -> a[b:]')
-s
尝试简化代码(在应用重写规则后,如果有的话)。
-w
不将重新格式化的源打印到标准输出。
如果文件的格式与 gofmt 不同,则用 gofmt 的版本覆盖它。
如果在覆盖期间发生错误,原始文件将从自动备份中恢复
-
注释
-
命名规范
变量:缩略词全大写;变量距离使用的地方越远,越需要携带更多的上下文信息 函数:函数名不携带包名的上下文信息;在返回类型T时,可以在函数名中加入类型 包:只有小写字母组成,不包含大写字母和下划线;不要与标准库同名;不使用常用变量名给包命名 -
控制流程
尽量保持正常代码路径为最小缩进
-
错误和异常处理
错误判定:
判定一个错误是否为特定错误,使用 errors.Is
不同于使用 == ,使用该方法可以判定错误链上的所有错误是否含有特定的错误
在错误链中获取特定种类的错误,使用errors.As
panic:
不建议在业务代码中使用panic
若问题可以被屏蔽或解决,建议使用error代替panic
当程序启动阶段发生不可逆转的错误时,可以在init或main函数中使用panic
recover:
只能在defer函数中使用
嵌套无法生效
只能在当前goroutine生效
defer的语句时后进先出
性能优化建议
- 推荐使用【Benchmark】
benchmark函数注意事项:
benchmark函数一般以Benchmark开头
benchmark函数也是test case之一,也会受TestMain限制
benchmark的case一般会跑b.N次,而且每次执行都会如此
在执行过程中会根据实际case的执行时间是否稳定会增加b.N的次数以达到稳态
go test -bench=. -benchmen
- slice 预分配内存
- 尽可能在使用make()初始化切片时提供容量信息
- 在已有切片基础上创建切片,不会创建新的底层数组
- 可使用 copy 代替 re-slice
-
map 预分配内存
-
使用strings.Builder
- 使用 + 拼接性能最差,且每次都会重新分配内存
- strings.Builder底层是byte数组
- 空结构体
- 空结构体struct{}实例不占据任何的内存空间
- 可作为各种场景下的占位符使用
- atomic包
- 锁的实现是通过操作系统来实现,属于系统调用
- atomic操作是通过硬件实现,效率比锁高
- sync.Mutex 应该用来保护一段逻辑,不仅仅用于保护一个变量
- 对于非数值操作,可以使用atomic.Value,能承载一个interface{}