高质量编程
正确可靠,简洁清晰
编程原则
- 简单性
- 可读性
- 生产力
编码规范
- 代码格式
- 注释
- 命名
- 控制流程
- 错误和异常处理
代码格式
gofmt会自动帮你整理格式
goimports (gofmt+依赖包管理),自动增删依赖包,将依赖包按照字母顺序排序分类
注释
作用,怎么work的,为什么要(提供上下文),什么情况会有异常/错误
命名
缩略词需要全部大小,如果不想暴露外部,需要统一小写,不要仅仅首字母小写
函数命名不需要携带包名的上下文信息,例如severice层的方法,在controller层调用是service.XXXFunc
包名使用小写,不含大写字母和下划线。不要与系统库重名,使用单数形式,尽量不要占用常用变量名
控制流程
减少嵌套,尽量展开
错误和异常处理
简单错误
- 指仅出现一次的错误,在其他地方不需要捕获该错误
- 优先使用errors.New 来创建匿名变量来直接表示简单错误
- 有格式化需求可以使用fmt.Errorf
错误的wrap和unwrap
- 错误的wrap可以让一个error嵌套一个error
fmt.Errorf使用%w关键字来讲一个错误关联至错误链中
错误判定
errors.Is可以帮助判断错误(链)上是否有特定错误errors.As可以帮助取特定类型error内容
panic,recover
不建议业务代码中使用panic,recover只能在被defer的函数中使用,嵌套无法生效
性能调优
go test -bench=. 建议在命令行使用,在vscode的console里使用output不全
goos: windows
goarch: amd64
pkg: go-project-example-day02/test
cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
BenchmarkFib20-8 48744 24838 ns/op 0 B/op 0 allocs/op
PASS
优化建议
- slice尽可能预分配内存
- 在已有切边上创建切片,新的切片引用老的切片,导致老切片内存无法被释放。所以建议用
copy替代 重新切片 - stringbuilder, stringbuffer 来字符串拼接
- 使用空结构体,可做map值占位
- 使用系统atomic包
原则
- 依靠数据,不靠猜测
- 定位最大瓶颈
- 不要过早优化
- 不要过度优化
工具pprof
准备工作
将pprof handler注册到http server中
import (
"log"
"net/http"
_ "net/http/pprof" // 注册
"github.com/EDDYCJY/go-pprof-example/data"
)
指标含义
Flat == Cum, 函数中没有调用其他函数
Flat == 0, 函数中只有其他函数调用
cpu占用查看
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
随即可以进行命令行的交互,如top
(pprof) top
Showing nodes accounting for 6.33s, 99.84% of 6.34s total
Dropped 1 node (cum <= 0.03s)
flat flat% sum% cum cum%
6.33s 99.84% 99.84% 6.34s 100% github.com/wolfogre/go-pprof-practice/animal/muridae/mouse.(*Mouse).Steal (inline)
0 0% 99.84% 6.34s 100% github.com/wolfogre/go-pprof-practice/animal/muridae/mouse.(*Mouse).Live
0 0% 99.84% 6.34s 100% main.main
0 0% 99.84% 6.34s 100% runtime.main
如果命令行键入web会跳转网页
可以看到CPU占用大户
再使用list,可以帮助更精确定位
heap堆内存占用情况
带上选项-http=:8080会打开图形化界面
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
会弹窗
选中VIEW->Source可以进一步进行排查,如图
修正过后,再次打开,好像不错
但是,刚刚我们仅是在 inuse_space(应用程序的常驻内存占用情况)中看到的,有没有可能一些内存是临时分配的呢(alloc_space)
切换到alloc_space后,我们发现有的
goroutine
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"
然后VIEW->Flame Graph
可以看到wolf.Drink方法占用了很多CPU时间
切换到Source,然后搜索wolf可以找到:然后进行修改
mutex 锁
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"
block 阻塞
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"
工具pprof原理(略,详见ppt)
业务案例
流程
-
确定性能评估手段
-
分析数据,定位性能瓶颈
-
重点优化项改造
要保证正确性,对比优化前后返回数据区别
-
验证