这是我参与「第五届青训营」伴学笔记创作活动的第 3 天
目录
-
高质量编程
- 高质量编程简介
- 编码规范
- 性能优化及建议
-
性能调优实战
- 性能调优简介
- 性能分析工具 pprof 实战
1.高质量编程
高质量编程简介
高质量的代码一般来说具备这几个特点:正确可靠、简洁清晰、高效可读
- 程序的正确可靠性表现在对于各种边界条件是否考虑完全
- 对于异常情况是否进行了处理
- 代码是否易于维护
编码规范
- 代码格式
- 注释
- 命名规范
- 控制流程
- 错误和异常处理
代码格式
推荐使用gofmt 自动格式化代码, gofmt 是Go官方提供的工具,能自动在你保存后为Go语言代码统一为官方风格
在项目中使用 gofmt 非常简单,只需要在控制台输入如下命令:
go get golang.org/x/tools/cmd/goimports
注释
对于函数注释,我们应该统一注释在函数上方,便于IDE进行解析,让我们不需要进行跳转也可以看到注释的内容。同时注释的内容应该精炼,说明功能与大概的执行逻辑。
代码其实就是最好的注释:如果代码表达的内容已经足够清晰,那么注释也应该相应少一些。
命名规范
变量名:简洁,缩略词全大写,准确表达变量的意义
//一个好的演示
func (c *Clinet) send(req *Request, deadline time.Time)
// 使用t命名后我们就不知道这里的t变量是拿来做什么的了
func (c *Clinet) send(req *Request, t time.Time)
包名:只由小写字母组成,不包含其他字符,不与标准库同名
函数名:简洁易读,能表达函数的功能
控制流程
- 保持最小缩进(能4个空格就不要使用8个空格)
- 处理的逻辑尽量为直线,避免过度复杂的嵌套
- 正常的流程代码应该沿着屏幕向下移动
错误和异常处理
简单错误
- 简单错误是指仅仅出现一次的错误,且其他的地方不需要捕获该错误
- 优先使用errors.New 来创建匿名变量来直接表示简单错误
- 需要格式化错误信息则可以使用 fmt.Errorf
func div(a int, b int) {
if b == 0 {
errors.New("div by zero")
}
return a / b
}
- Wrap与Unnwrap
err1 := errors.New("new error")
err2 := fmt.Errorf("err2: [%w]", err1)
err3 := fmt.Errorf("err3: [%w]", err2)
fmt.Println(errors.Unwrap(err3))
fmt.Println(errors.Unwrap(errors.Unwrap(err3)))
// output
err2: [new error]
new error
错误判定
errors.ls 和 errors.As
当错误被多层包装后,我们如何在调用链上游判断其是否为底层中的一个错误呢?
使用errors.ls,它递归调用 Unwrap 并判断每一层的 err 并进行判断,如果有任何一层 err 和传入的目标错误(target)相等,则返回 true。
err1 := errors.New("new error")
err2 := fmt.Errorf("err2: [%w]", err1)
err3 := fmt.Errorf("err3: [%w]", err2)
fmt.Println(errors.Is(err3, err2))
fmt.Println(errors.Is(err3, err1))
// output
true
true
panic 和 recover
panic对于程序来说是出现了毁灭性的错误,比如内存泄露等等(此时我们无法继续运行程序,只能被迫中断)
所以在业务代码中对于异常的处理是很少使用panic的,这会极大的降低用户对我们程序的使用体验感。
大多数可以挽救的错误我们一般是使用recover来进行处理,让程序回到正常的流程当中继续运行。
具体的使用可以见:【Go基础】panic & recover - 掘金 (juejin.cn)
2.性能调优实战
性能调优简介
原则
- 依靠数据而不是凭猜测
- 定位到最大的瓶颈,而不是细枝末节
- 不要过早优化
- 不要过度优化
性能分析工具 pprof 实战
pprof 是 Go 语言中分析程序运行性能的工具,它能提供各种性能数据:
- allocs: 内存分配情况
- blocks: 阻塞操作情况
- cmdline: 显示程序启动命令及参数
- goroutine: 显示当前所有线程的堆栈信息
- heap:堆上内存的使用信息
- mutex:锁的使用情况
- profile: cpu占用的情况
- threadcreat:系统线程创建的信息
- trace: 程序运行跟踪信息
先将pprof练习项目下载到本地
git clone https://github.com/google/pprof
运行:
可以看到内存占用瞬间就高起来了。接下来我们将使用pprof工具定位到代码中导致内存占用飙高的代码,并进行优化或删除。
控制台输入:
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
可以看到Eat这个方法导致了大部分的内存占用
使用 list 正则表达式 输出具体函数的代码
list Eat
不过控制台使用不方便去进行查看,我们可以使用web命令(这步需要在cmd或powershell下输入,出现错误往下看),打开浏览器,使用图形化界面进行查看
tips:如果你在使用web命令时出现了如下错误:
failed to execute dot. Is Graphviz installed? Error: exec: "dot": executable file not found in %PATH%
首先idea内置的控制台界面好像是没法使用这个命令的(等待验证)
其次就是说明你的电脑缺少GraphvizDownload | Graphviz
安装完成后,记得将Graphviz的bin目录添加到环境变量PATH中
一切完成后就可以了。
同时,我们还可以使用更好用的UI界面
tips:URL最后一个参数就是我们需要查看的性能指标了(这里我们查看heap的使用情况)
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
最后我们通过分析,找到了引起内存飙高的代码处并进行了优化。