高质量编程与代码规范 | 性能优化 | 青训营笔记

128 阅读2分钟

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

高质量编程与代码规范 | 性能优化 | 青训营笔记

高质量编程

目标:正确可靠、简洁清晰

  • 边界条件是否完备
  • 异常处理,稳定性保证
  • 易读易维护

规范

  • 公共符号(变量、常量、函数)始终要注释,提供额外的上下文信息。应该解释:1)代码作用 ;2)如何做的; 3)实现的原因;4)什么情况会报错
  • 代码格式:推荐gofmt自动格式化代码,goimports进行依赖包管理

命名规范

image.png

image.png

image.png

控制流程

  • 避免分支嵌套
  • 尽量保持正常代码路径为最小缩进(优先处理异常和特殊情况)
  • 线性原理,处理逻辑尽量走直线,正常代码流程沿着屏幕向下移动

image.png

错误可异常处理规范

  • 简单错误(仅出现一次,在其他地方不需要捕获)优先使用errors.New来创建匿名变量直接表示简单错误,如果有格式化需求使用fmt.Errorf
  • error的跟踪连可用warp
  • 判定是否为特定错误使用errors.Is
  • 获取特定种类错误,使用errors.As

image.png

  • 不建议在业务代码中使用panic,只适用于真正异常,不启动没法运行的情况
  • recover:只能在被defer的函数中使用,嵌套无法生效,只在当前goroutine生效。打印panic上下文,在log中记录调用栈。
  • defer语句会在函数返回前调用,多个defer语句是后进先出

性能优化

如何使用?

要用实际数据衡量。Go提供了支持基准性能测试的benchmark工具 go test -bench=. -benchmem

性能优化建议

  • slice预分配内存:尽量在初始化时制定容量,减少获取内存分配次数
    • 创建一个新的切片会复用原来切片的底层数组。
  • map预分配内存:make预分配大小,不断向map添加元素会触发扩容
  • 字符串处理:直接相加性能差,最好使用strings.Builder(更高效)或者bytes.Buffer

image.png

image.png

  • 空结构体节省内存 可以用map实现set,因为只需要map的键,而不需要值
    m := make(map[int]struct{})

  • 多线程

image.png 用atomic包比加锁要好。因为锁是通过系统实现,属于系统调用,atomic操作通过硬件实现,效率比锁高。仅保护一个变量可考虑用atomic包,sync.Mutex应该用于保护一段逻辑。

性能调优实战

原则

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

性能分析工具pprof

image.png