Go 高质量编程与性能调优 | 青训营笔记

96 阅读4分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 3 天

今日内容

学习完了青训营课程 后端入门 - Go 语言原理与实践 中的 高质量编程简介及编码规范性能优化指南性能优化分析工具性能调优实战案例 之后的一些总结。

课程内容

  1. 高质量编程
  2. 性能调优实战

1. 高质量编程

1.1 简介

  1. 什么是高质量:编写的代码能够达到正确可靠、简洁清晰的目标
    • 各种边界条件是否考虑完备
    • 异常情况处理,稳定性保证
    • 易读易维护
  2. 编程原则:实际场景千变万化,但是遵循的原则相同
    • 简单性
    • 可读性
    • 生产力

1.2 编码规范

  • 代码格式
    • GoLand 默认的就挺好用的
  • 注释
    • 注释应该解释代码作用
    • 注释应该解释代码如何做的
    • 注释应该解释代码实现的原因
    • 注释应该解释代码什么情况会出错
  • 命名规范
    • 变量
      • 简洁胜于冗长
      • 缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写
      • 变量距离其被使用的地方越远,则需要携带越多的上下文信息
      • 不冗余也包含了足够的信息量
    • 函数
      • 函数名不需要携带包名的上下文信息,因为包名和函数名总是成对出现的
      • 函数名尽量简短
      • 当名为 foo 的包某个函数返回类型 Foo 时,可以省略类型信息而不导致歧义
      • 当名为 foo 的包某个函数返回类型 T 时(T 并不是 Foo),可以在函数名中加入类型信息
      • 只由小写字母组成,不包含大写字母和下划线等字符
      • 简短并包含一定的上下文信息。例如 schema、task等
      • 不要与标准库同名
  • 控制流程
    • 避免嵌套
    • 尽量保持正常代码路径为最小缩进(B 站和油管上有些 up 会讲方法)
      • 优先处理错误和特殊情况尽早返回
      • ...
  • 错误和异常处理
    • 简单错误:仅会出现一次,且在其他地方不需要不需要捕获的错误
      • 优先使用 errors.New() 来创建匿名变量来直接表示简单错误
      • 如有格式化要求,使用 fmt.Errorf()
    • 错误的 wrap 和 unwrap
    • 错误的判定
      • 判定一个错误是否为特定的错误,用 errors.Is(),不同于 ==,该方法可以判定错误链上的所有错误是否含有特定的错误
      • 在错误链上获取特定种类的错误,使用 errors.As()
      • panic() 不建议在业务代码中使用,但是可以在 initmain 中使用
      • recover() 只能在被 defer 的函数中使用,嵌套无法生效,只在当前 goroutine 生效

1.3 性能优化建议

  • benchmark
    • 如何使用(建议配合 GoLand)
  • slice 预分配内存
  • map 预分配内存
  • 字符串处理,使用 strings.Builder
  • 空结构体
  • atomic

2. 性能调优实战

2.1 性能调优原则

  • 要依靠数据不是猜测
  • 要定位最大瓶颈而不是细节
  • 不要过早优化
  • 不要过度优化

2.2 性能分析工具 pprof

  • 功能简介
  • 使用笔记
    • 在程序中 http.ListenAndServe(":6060", nil) 开启监听,浏览器访问 http://localhost:6060/debug/pprof/ 可以查看到一些信息

    • 在终端使用 go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10" 进行 10 秒的采样并进入到 pprof 中

    • 可在 pprof 中使用 top 命令,参数说明 image.png

      • flat 当前函数本身的执行耗时
      • flat% flat 占 CPU 总时间的比例
      • sum% 上面每一行的 flat% 总和
      • cum 当前函数本身加上其调用函数的总耗时
      • cum% cum 占 CPU 总时间的比例
    • list Reg 根据指定的正则表达式查找代码行 image.png

    • web 命令在网页中可视化查看 image.png

    • go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap" 快捷查看堆内存 image.png

    • 切换各种不同的视图发现还有大量申请内存的情况 image.png

    • go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine" 快捷查看协程情况,切换到火焰图更清晰 image.png

    • 根据火焰图查看占用 cpu 时间长的协程,切换到 source 视图,查找问题所在 image.png

    • go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex" 排查互斥量出现的问题 image.png

    • 同样切换到 source 视图,查找问题所在 image.png

3. 小结

pprof 需要多多练习,在实际生产中多加掌握,有助于提高代码质量,更快找到问题所在。