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

77 阅读3分钟

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

1.本堂课重点内容

  • 如何编写更简洁清晰的代码
  • 常用Go语言程序优化手段

2.具体案例

3. 如何编写更简洁清晰的代码

3.1 高质量编程

3.1.1 简介

什么是高质量
编写的代码能够达到正确可靠、简洁清晰的目标可称之为高质量代码

  • 各种边界条件是否考虑完备
  • 异常情况处理,稳定性保证
  • 易读易维护
3.1.2 编程原则
  1. 简单性
  2. 可读性
  3. 生产力
3.1.3 编码规范
  • 代码格式
  • 注释
  • 命名规范
  • 控制流程
  • 错误和异常处理

代码格式
gofmt Go 语言官方提供的工具,自动格式化Go语言代码为官方统一风格 goimports 管理依赖包、自动增删依赖的包引用

注释

  • 包中声名的每个公共的符号:变量、常量、函数以及结构都需要添加注释
  • 任何既不明显也不简短的公共功能必须予以注释
  • 无论长度或复杂程度如何,对库中的任何函数都必须进行注释
    例外
  • 不需要注释实现接口的方法

命名

  • 简介胜于冗长
  • 缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写

控制

  • 避免嵌套,保证正常流程清晰

    eg:

        if bool {
            return xx;
        } else {
            return xxx;
        }
        
        //优化
        if bool {
            return xx;
        }
        return xxx;
    
  • 尽量保证正常代码路径为最小缩进 优先处理错误情况,尽早返回或继续循环来减少嵌套 eg:

        func OneFunc() error{
            err := doSomething()
            if err == nil{
                err := doAnytherThing()
                if err == nil{
                    return nil
                }
                return err
            }
            return err
        }
        
        //优化
        func OneFunc() error{
            if err := doSomething(); err != nil{
                return err
            }
            if err := doAnotherThing(); err != nil {
                return err
            } 
            return nil
        }
    

错误和异常处理

  • 简单错误

    简单错误指的是仅出现一次的错误,且在其他地方不需要捕获该错误 优先使用errors.New来创建匿名变量来直接表示简单错误

    return errors.New("This is a error")
    

    如果有格式化需求,使用fmt.Errorf

  • 复杂错误

    错误的Wrap实际上提供了一个error嵌套两一个error的能力,从而生成一个error的跟踪链
    在fmt.Errorf中使用:w%关键字来将一个错误关联至错误链中

  • 错误判定

    判定一个错误是否为特定错误,使用errors.Is 不同于使用==,使用该方法可以判定错误链上的所有错误是否含有特定的错误 使用errors.As 可以把错误的内容取出来

  • panic 不建议在业务代码中使用panic 调用函数不包含recover会造成程序崩溃 若问题可以解决或被屏蔽,建议使用error代替panic

  • recover

    生效范围: 在当前goroutine的被defer的函数中生效 嵌套无法生效 defer语句是后进先出

4. 常用Go语言程序优化手段

4.1 性能优化建议

  • 性能优化的前提是满足正确可靠、简洁清晰等质量因素
  • 性能优化是综合评估,有时侯时间效率和空间效率可能对立
  • 针对go特性,介绍go相关的性能优化建议

4.2 Benchmark

  • 性能表现需要实际数据衡量
  • Go语言提供了支持基准性能测试的benchmark工具
go test -bench= . -benchmem

4.3 Slice预分配内存

  • 尽可能在使用make()初始化切片时提供容量信息
  • 在已有切片基础上创建切片,不会创建新的底层数组
  • 使用copy代替re-slice

4.4字符串处理

  • strings.Builder
  • ByteBuffer
  • 直接使用+号不推荐 性能最差

4.5 空结构体

  • 空结构体struct{}实例不占据任何的内存空间
  • 可作为各种场景下的占位符使用