编码规范
-
代码格式
使用gofmt格式化代码,使用goimports工具进行包导入管理(可以自动导入包,去除不适用的包,并按字典序排列,节省时间)
-
注释
- 代码是最好的注释
- 注释应该提供代码未表达出的上下文信息
-
命名规范
- 核心目标是降低阅读理解代码的成本
- 重点考虑上下文信息,设计简洁清晰的名称
-
控制流程
- 线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支
- 正常流程代码沿着屏幕向下移动
- 提升代码可维护性和可读性
- 故障问题多出在复杂的循环语句和条件语句中
-
错误和异常处理
- error尽可能提供简明的上下文信息链,方便定位问题
- panic用于真正异常的情况
- recover生效范围,在当前goroutine的被defer函数中生效
关于编码规范其实很多点都需要在实际的开发过程中去体会规范为什么这么设计以及一些具体的Best Practice是如何应用的,课堂上已经总结了不少,这里推荐阅读Go代码Review建议,它可以看作effective go的一个补充。下面我列出一些review建议中比较简单实用但是可能一开始不会注意到的内容
- 用完整的句子写注释方便自动化展示,句子开头为所注释的东西,多句的话第一句作为摘要
- 不要引用其他包的内存(防御式编程)
- 使用
crypto/rand替代math/rand,更加安全 - 错误信息不大写,不要句号,因为错误信息一般都被包括在上下文中
- 接口放在使用方的package中而不是实现方的package,简单来说在接口只有在被使用的地方才定义
- 行的长度应该根据语义而定,不要死守80字符的“规矩”,现在的显示设备已经很先进了,但是一样要避免过长的行
- go中返回值可以有名字,但是要注意不要添加冗余的名字,例如
err error就毫无意义,如果有多个同类型返回值加个名字会好很多 - 不要用
this,me,self给某个类型方法的接收方对象命名(就像这样func (this Hello) hello())
性能优化建议
- 使用Benchmark来衡量性能表现
- Slice预分配内存以减少内存申请,提高运行速度
- Slice使用copy替代re-slice来减少内存占用,节省内存空间
- Map预分配内存
- 字符串处理使用strings.Builder
- 空结构体节约内存,利用其语义特征,同时不耗费资源(利用map实现set)
- atomic包原子化操作提高性能
性能调优实战
首先直接从GitHub中clone下来的项目是没有go.mod文件的,而go1.18强制使用module来管理项目,所以需要我们自己生成go.mod文件,具体运行以下命令
bash
复制代码
$ go mod init github.com/wolfogre/go-pprof-practice
$ go mod tidy
会生成如下的go.mod文件
go
复制代码
module github.com/wolfogre/go-pprof-practice
go 1.18
可以看到是没有外部依赖的。
其次需要注意这里的module名字不能修改,只能是github.com/wolfogre/go-pprof-practice,如果你使用了其他的名字,例如go-pprof-practice,则会生成这样的go.mod文件
go
复制代码
module go-pprof-practice
go 1.18
require github.com/wolfogre/go-pprof-practice v0.0.0-20190402114113-8ce266a210ee
虽然程序也能运行,但是依赖的却是GitHub上的仓库(go mod tidy会将这个包拉下来存到你的gopath里面),你修改你本地tiger.go文件中的内容,main函数的运行结果是不会变的。