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

42 阅读2分钟

高质量编程&性能调优实战

1.高质量编程

1.1 编码规范

1.1.1 注释

  • 应该解释代码作用->提供有用信息
    • 注释公共符号
  • 解释代码是如何做的
  • 代码实现的原因
    • 外部因素
    • 提供额外上下文
  • 什么情况下会出错

1.2.1 命名规范

  • 变量
    • 简介胜于冗长
    • 缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写
      • 例如使用ServeHTTP而不是ServeHttp
      • 使用XMLHTTPRequest或者xmlHTTPRequest
    • 变量距离其被使用的地方越远,则需要携带越多的上下文信息
  • 函数
    • 函数名不携带包名的上下文信息,因为包名和函数名总是成对出现的
    • 函数名尽量简短
    • 只由小写字母组成。
    • 不包含大写字母和下划线等字符简短并包含一定的上下文信息。例如schema、task 等不要与标准库同名。例如不要使用sync或者strings

1.2.2 控制流程

  • 避免嵌套,保持正常流程清晰
  • 尽量保持正常代码路径为最小缩进

1.2.3 错误和异常处理

  • error尽可能提供简明的上下文信息链,方便定位问题
  • panic用于真正异常的情况
  • recover生效范围,在当前goroutine的被defer的函数中生效

1.3 性能优化建议

1.3.1使用Benchmark

1.3.2 Slice

  • 尽可能在使用make()初始化切片时提供容量信息

切片本质是一个数组片段的描述,包括数组指针,片段长度和容量,创建切片会服用原来切片的底层数组

  • 大内存未释放 - 可以使用copy代替re-slice
    • 场景:
      • 原切片较大,代码在原切片基础上新建小切片
      • 原地城数组在内存中有引用,得不到释放

1.3.3 Map

map预分配内存

原因:不断向map中添加元素的操作会触发map的扩容提前分配好空间可以减少内存拷贝和Rehash的消耗建议根据实际需求提前预估好需要的空间

字符串处理

  • 使用+拼接性能最差,strings.Builder,bytes.Buffer相近,strings.Buffer 更快,原因:
    • 字符串在Go语言中是不可变类型,占用内存大小是固定的
    • 使用+每次都会重新分配内存
    • builder 和 buffer底层都是[]byte数组
    • 内存扩容策略,不需要每次拼接重新分配内存

atomic包

  • 硬件实现,效率比锁高
  • 锁的实现通过操作系统,系统调用

1.4 小结

  • 避免常见的性能郜陷阱可以保证大部分程序的性能
  • 普通应用代码,不要一味地追求程序的性能
  • 越高级的性能优化手段越容易出现问题
  • 在满足正确可靠、简洁清晰的质量要求的前提下提高程序性能

2.性能调优实战

大部分都是实战内容。