性能优化|青训营笔记

54 阅读3分钟

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

高质量编程

什么是高质量:

  • 各种边界条件是否考虑完备
  • 异常情况处理,稳定性保证
  • 易读易维护

编程原则:

  • 简单性

    • 消除”多余负责写“,简单清晰的逻辑编写代码
    • 不理解的代码无法修复改进
  • 可读性

    • 代码是写给人看的
    • 编写可维护代码的第一步是确保代码可读
  • 生产力

    • 团队整体工作效率

编码规范

  • 代码格式

    • 使用gofmt自动格式化代码,使用goimports(增加了依赖包格式化功能)
  • 注释(快让我吐槽一下go的注释又臭又长)

    • 注释应该解释代码的作用
    • 注释应该解释代码如何做的
    • 代码应该解释代码实现的原因
    • 代码应该解释代码什么情况下会出错
  • 命名规范

    • 变量

      • 缩略词全部大写,但位于变量开头且不需要导出时,用小写
      • 变量距离使用的地方越远,越需要携带多的上下文信息
    • 函数

      • 函数名尽量简短,函数名不携带包名的上下文信息,因为包名和函数名总是一起出现的
      • 函数名与包名一直时可以省略类型信息,不一致时需要加上类型信息
      • 只用小写字母,不包括大写和下划线
      • 简短并只包含一定的上下文信息
      • 不要与标准库同名
      • 不要使用常用变量作为报名,例如使用bufio而不是buf
      • 使用单数
      • 谨慎使用缩写,缩写尽量是公共承认的缩写
  • 控制流程

    • 避免嵌套,保持正常流程清晰,例如if else都进行返回,那可以省略else
    • 不建议使用嵌套结构,尽量使用 线性进行异常情况、错误流程判断
  • 异常处理

    • 简单错误

      • 仅出现一次的错误,且不需要在其他地方捕获的
      • 优先使用errors.New创建匿名变量来直接表示简单错误
      • 如果有格式化需求,使用fmt.Errorf
    • 复杂错误

      • 错误的Warp实际上是提供了一个error嵌套另一个error能力,从而生成一个error跟踪链
      • 在fmt.Errorf中使用%w来将一个错误关联至错误链中
    • 错误判断

      • 错误链上是否包含特定种类的错误error.As
    • panic

      • 不建议在业务中使用panic,但是可以在程序启动阶段发生不可逆的错误,可以在init或者main函数中使用panic
    • recover(处理panic)

      • recover只能在defer被使用
      • 嵌套无法生效
      • 只能在goroutine生效

性能优化

评估性能

  • Go提供了benchmark工具,可以使用go test -bench=. -benchmem

image-20230120181728398

性能优化

  • slice切片,提前分配内存

    • 尽可能在使用make()初始化切片时提供容量信息
    • 和Java一样,不进行预分配需要先创建一个新的数组,并进行拷贝
    • 另一个陷阱image-20230120182335086
  • map预分配内存

    • 和slice同理
    • image-20230120183104827
  • 字符串处理(同样像极了Java)

    • 使用strings.builder

      • bytes.buffer转换为字符串时重新申请了一块空间
      • strings.builder直接将底层的[]byte转换成了字符串类型返回
      • image-20230120183401099
      • 预知字符串长度方法,用grow方法预分配内存
  • 使用空结构体节省内存

    • 使用场景set
    • image-20230120184021430
  • atomic包

    • 使用atomic包比加锁性能优秀很多

      • 锁是通过操作系统实现的,atomic是通过硬件实现的,效率比锁高
      • 用锁更倾向于保护一段逻辑,而不是一个变量

引用

  1. 稀土掘金内部课 后端入门 - Go 语言原理与实践