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

35 阅读2分钟

高质量编程

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

1. 编码规范

1.1 代码格式

  • 推荐使用gofmt自动格式化代码

1.2 注释

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

1.3 命名规范

  • 简洁
  • 缩略词全大写,但当其位于变量开头且不需要导出时,使用全大写
  • 变量距离其被使用的地方越远,则需要携带越多的上下文信息

1.4 控制流程

  • 线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支
  • 正常流程代码沿着屏幕向下移动
  • 提升代码可维护性和可读性
  • 故障问题大多出现在复杂的条件语句和循环语句中

1.5 错误和异常处理

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

2.性能优化建议

2.1 Benchmark

2.2 Slice

  • 切片本质是一个数组片段的描述
    • 包括数组指针
    • 片段的长度
    • 片段的容量(不改变内存分配情况下的最大长度)
  • 切片操作并不复制切片指向的元素
  • 创建一个新的切片会复用原来切片的底层数组

2.3 Map

  • map预分配内存
    • 不断向map中添加元素的操作会促发map的扩容
    • 提前分配好空间可以减少内存拷贝和Rehash的消耗
    • 建议根据实际需求提前预估好需要的空间
  • 字符串处理
    • 使用+拼接性能最差,strings.Builder,bytes.Buffer相近,strings.Buffer更快
    • 分析
      • 字符串在golang中是不可变类型,占用内存大小是固定的
      • 使用+每次都会重新分配内存
      • strings.Builder,bytes.Buffer底层都是[]byte数组
      • 内存扩容策略,不需要每次拼接重新分配内存
  • 空结构体
    • 空结构体struct{}实例不占据任何的内存空间
    • 可作为各种场景下的占位符使用
      • 节省资源
      • 空结构体本身具备很强的语义,即这里不需要任何值,仅作为占位符
  • atomic包
    • 锁的实现是通过操作系统来实现,属于系统调用
    • atomic操作是通过硬件实现,效率比锁高
    • sync.Mutex应该用来保护一段逻辑,不仅仅用于保护一个变量
    • 对于非数值操作,可以使用atomic.Value,能承载一个interface{}