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

49 阅读2分钟

这是我参与「第五届青训营 」笔记创作活动的第5天。生产开发中,对高质量编程的要求越来越多。以下是一些提升编程简洁性,可读性,高效性的方法。

编写高质量Go代码的规范主要有:代码格式,注释,命名规范,控制流程,错误和异常处理。

代码格式辅助包:

  • gofmt
  • goimports

注释:公众符号,实现过程,代码限制条件,不需要注释实现接口的过程。

命名规范:简洁,缩略词全大写(位于变量开头且不需要导出则全小写),变量使用域越远则变量名携带信息越多。注:函数名如果返回类型,可以省略类型信息;pkg名全部小写。

控制流程注意点:

  • 避免嵌套
  • 尽量保持正常代码流程为最小缩进(优先处理错误or特殊情况),如下:
    func OneFunc() error{
        err := doSomething()
        if err==nil{
            err := doAnotherThing()
            if err==nil{
                return nil
            }
            return err
        }
        return err
    }

总而言之,代码控制流程遵循线性原理,处理逻辑走直线。

错误和异常处理:

  • 简单错误:仅出现一次且不需要捕获。用errors.New匿名变量表示。格式化输出需求:fmt.Errorf
  • Wrap,UnWrap:(Go官方提供errors.Is, errors.As, errors.Unwrap)生成error跟踪链,从一个error嵌套到另一个,fmt输出中用%w将错误关联至错误链。errors.Is获取特定错误,errors.As获取特定种类错误
  • panic:程序启动阶段发生不可逆转错误,在init或main函数中使用
  • recover:针对协程,只能对被defer的函数使用,只能在当前goroutine使用(后进先出,类似栈)

更多性能优化建议:

  • Benchmark
  • slice---数组片段的描述,包括数组指针,片段长度,容量等。建议预分配内存,在make初始化切片时提供容量信息
    data:=make([]int,0,size)

已有切片底层创建新的切片,底层数组不会变化。这里用copy替代re-slice会更好。

-map预分配内存

    data :=make(map[int]int,size)

预分配可以减少内存拷贝和Rehash的消耗。

  • 字符串建议string.Builder
  • 空结构体可以作为占位符,不占用任何内存空间但具有很强的语义,节省内存
  • 使用atomic包进行原子操作,如加锁等,通过硬件实现,效率比较高

总而言之,性能调优应遵循以下原则:

  • 避免常见性能陷阱
  • 普通应用代码,不要一味追求性能而将代码复杂化
  • 正确可靠,简洁清晰