Go 高质量编程与性能调优 | 青训营笔记
这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天,主要记录相关的知识点。
本堂课重点内容
- 高质量编程
- 性能调优
- 单元测试
- 项目实战
高质量编程
对于编码的质量问题,有非常多的评价标准,但普遍来说,一个高质量的代码通常都具有如下特点:
- 正确可靠,边界考虑完备
- 异常处理、稳定性保证
- 可读性强,可维护
简单而言,需要保证代码具有 简单性、可读性与生产效率保证 的特点。
注释
注释需要给出代码未明确给出的上下文信息,例如:
- 做什么
- 怎么做
- 为什么这么做
- 错误的处理
对于公共的符号,需要给出注释。
代码格式
可以使用一些工具来帮助实现优美的代码格式:
命名规范
有一些公共的,统一的变量命名规范,例如:
- 缩略词全大写,除非其位于变量开头且不需要导出时(全小写)
- 变量距离其被使用的地方越远,需要携带更多的上下文信息,比如全局变量
对于函数,也有一些命名规范:
- 函数名尽量简短
- 函数名不需要携带包名的上下文信息
- 当包名(比如 )与返回类型(比如 )一致时,可以省略类型信息避免歧义
- 当包名(比如 )与返回类型(比如 )不一致时,可以添加类型信息明确含义
对于包,也有一些命名规范可以参考:
- 只有小写字母构成,不包含大写字母、下换线等符号
- 简短,并包含一定的上下文信息
- 避免与标准库同名
- 避免与经常使用的变量重名,比如
- 使用单数而非负数
- 缩写谨慎使用,保证含义可以被广泛接受
流程控制
在实际的流程控制结构中,我们可以:
- 避免不必要的流程嵌套,保证流程清晰
- 优先处理错误或特殊情况,尽早返回或减少循环次数减少嵌套行为的发生
- 保持代码使用最小缩进
错误与异常处理
在错误处理中,对于一个仅发生一次,且其他地方不需要捕获该错误的情况:
- 优先考虑使用
- 需要格式化,使用
对于复杂情况,我们可以形成一个错误的跟踪链,通过跟踪链来找到错误:
- 使用 来让一个 嵌套另外的
- 在 中使用 来将一个错误关联到一个错误链中
有时,我们需要判断一个错误是否是指定类型的错误,这时候可以用 ,使用该方法可以同时判断错误链上的所有错误是否包含该错误。
还可以用 可以查看特定种类错误的内容。
另外,不建议在业务中使用 ,因为一旦使用 而不 的话,那么程序会直接崩溃。
对于 ,其:
- 只能在当前的 生效
- 只能在被 的函数中使用
- 嵌套无法生效
- 后进先出
性能调优
在实际业务中,性能调优也是很重要的一个部分,下面将简单讲述其中的几个技巧。
预分配
是 中非常常用的数据类型,其自动分配扩容内存的特性在很多时候帮助简化了实际的编码,但是也因为这个机制,可能会导致不必要的扩容问题。
为了减少因为 自动扩容分配内存,我们可以在 时就设置好容量。类似的 也可以进行预分配。
使用 copy 代替 re-slice
对于一个切片,再进行切片操作,不会释放原有的内存空间,这就意味着原来的容量很大的切片(底层数组)并不会得到释放。
尽量使用 strings.Builder 来拼接字符串
常用的拼接字符串的方法有 , 和 ,在这三种方法中,使用 会导致每次拼接都会重新分配内存,导致运行速度慢; 会在最后返回时进行一次内存分配并返回字符串;而 是直接通过 来转换成字符串返回,不存在内存分配的过程,因此速度最快。
使用空结构体
一个空的结构体 是不会占用内存空间的,因此,在某些场景下可以作为占位符使用。
比如:实现一个
使用 atomic
使用 包可以进行一些原子操作,是通过硬件实现的,因此具有很高的效率。
Pprof工具
为了实现良好的优化,我们可以使用辅助工具 来帮助我们实现性能优化。
总结起来可以被概括如下:
可以在浏览器中输入如下内容启动 :
localhost:端口/debug/pprof
可以对不同信息进行采样,一个通用的的语句为:
go tool pprof -http=:新端口号(一般写8080即可) "http://localhost:6060/debug/pprof/参数"
CPU
可以通过如下命令查看函数占用 运行时间情况。
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=秒数"
等待运行结束,此时会进入 终端,输入 查看结果
参数解释:
- 当前函数本身的执行耗时
- 为 占 运行时间的百分比
- 从上往下的 之和
- 当前函数本身加上其调用函数的总耗时
- 为 占 运行时间的百分比
当 == 时,说明当前函数不会调用其他函数。
当 == ,说明当前函数自身不产生消耗。
由于上面发现 方法占用了大量时间,我们可以使用 来列出该函数。
list Eat
我们还可以使用 可视化。
web
Heap
使用如下命令:
go tool pprof -http=:8081 "http://localhost:6060/debug/pprof/heap"
我们可以在这里调整要查看的视图:
使用 可以排序展示。
使用 可以快速定位到问题:
在 中可以指定采样:
- 程序累计申请的对象数
- 程序累计申请的内存大小
- 程序当前持有对象数
- 当前占用的内存大小
Goroutine
使用如下命令:
go tool pprof -http=:8081 "http://localhost:6060/debug/pprof/goroutine"
类似,使用 定位。
Mutex
使用如下命令:
go tool pprof -http=:8081 "http://localhost:6060/debug/pprof/mutex"
类似,使用 定位。
Block
使用如下命令:
go tool pprof -http=:8081 "http://localhost:6060/debug/pprof/block"
类似,使用 定位。
个人总结
本次课程主要学习了:
- 高质量编程
- 性能调优