go语言优化| 青训营笔记

151 阅读2分钟

这是我参与「第三届青训营-后端场」笔记创作活动的第1篇笔记,课程的内容是关于高性能go语言发行版优化和落地实践。

go语言的优化是从多方面入手的,从命名规范到实际编码中的错误处理,以及逻辑的优化,下面对课中的这些内容做如下总结:

命名规范
  • 变量名:应该尽量简短,在不导出的情况下,使用小写,名称的含义要与上下文相关联

  • 函数名:函数名无需携带包名信息,也尽量简短

  • 包名:只能由小写字母组成,避免与标准库冲突

  • 提高代码的可读性
错误和异常处理
  • 简单错误处理:优先使用 errors.New 来创建匿名变量来直接表示该错误。有格式化需求时使用 fmt.Errorf,错误的 Wrap 和 Unwrap在 fmt.Errorf 中使用 %w 关键字来将一个错误 wrap 至其错误链中

  • 错误判定:使用 errors.Is 可以判定错误链上的所有错误是否含有特定的错误。在错误链上获取特定种类的错误,使用 errors.As

  • panic

    • 不建议在业务代码中使用 panic
    • 如果当前 goroutine 中所有 deferred 函数都不包含 recover 就会造成整个程序崩溃
    • 当程序启动阶段发生不可逆转的错误时,可以在 init 或 main 函数中使用 panic
  • recover

    • recover 只能在被 defer 的函数中使用,嵌套无法生效,只在当前 goroutine 生效
    • 如果需要更多的上下文信息,可以 recover 后在 log 中记录当前的调用栈。 其中需要注意的点:
  • panic 用于真正异常的情况

  • error 尽可能提供简明的上下文信息,方便定位问题
  • recover 生效范围,在当前 goroutine 的被 defer 的函数中生效

性能优化

  • 在满足正确性、可靠性、健壮性、可读性等质量因素的前提下,设法提高程序的效率
  • 我们可以在字符串处理或者切片的操作上入手,比如go的切片非常类似于c++的vector 都会在不断增加元素的过程中发送扩容,所以这里如果预先知道会有多少元素被添加,提前设定好切片的长度,就可以避免多次扩容导致的性能下降,以此类推,map也是如此,可以提交分配,避免rehash。其次在使用切片的时候使用使用 copy 替代 re-slice可以避免内存得不到释放。 对于字符串的处理尽量使用strings.Builder ,因为它和 bytes.Buffer 底层都是 []byte 数组,bytes.Buffer 转化为字符串时重新申请了一块空间,存放生成的字符串变量,而 strings.Builder 直接将底层的 []byte 转换成了字符串类型返回