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

77 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3天,今天学习了Go高质量代码规范以及性能调优的知识下面是我的笔记

Go高质量编程及性能调优

1、高质量编程

1.1、高质量编程的意义

​ 编写的代码能够正确可靠,简洁清晰

  • 简单性:消除多余的复杂性,以简单清晰的逻辑写代码,不理解的代码无法修复改进
  • 可读性:代码是写给人看的,不要写的太花
  • 生产力:注重团队工作效率

1.2、编码规范

  • 注意合理编写注释
    1. 注释应该解释代码作用
    2. 注释应该解释代码实现的原因
    3. 注释应该解释代码什么时候可能出错
  • 公共符号始终要注释
    1. 包中声明的公共符号,变量,常量,函数,结构体,都要注释
    2. 任何不明显不简短的公共功能,要注释。
    3. 无论长度或者复杂的程度,对库中的任何函数都要进行注释。
    4. 对实现接口的方法不需要注释,而是要注释出方法究竟实现了什么功能。
  • 命名规范
    1. variable变量:简洁为佳,注意达意,函数参数要做到英文不要过于笼统,例如对于 Time类对象,可以分别命名为,deadline,beginTime,nowTime,等等而不是t。
    2. function函数:不携带包的信息,因为与包是成对出现的,不要将函数名命名与关键字类似,例如http包中,命名func不需要再命名成serverhttp()这种,直接server()就行
    3. package:只有小写字母完成,简短包含上下文,不要与标准库重名,不使用复数而是单数,缩写谨慎,
  • 控制流程
    1. 避免分支嵌套,尽量减少else。
    2. 提升可读性,拒绝无脑多重循环和条件语句
  • 错误和异常的处理
    1. 简单错误使用errors.New即可,力求简洁
    2. 复杂错误 使用fmt.Errorf(format string,err error)格式化输出。
    3. 错误判定 errors.Is ,判断是否是某种错误(可自定义)
    4. 错误判定 errors.As,取出错误链中的错误
    5. 不建议在业务中使用panic(恐慌),当程序启动阶段发生不可逆转的错误,可以在init(),main()函数中panic
    6. recover:如果需要更多上下文信息,可以在recover后再log中记录当前的调用栈,recover仅仅在当前的goroutine被defer的函数中。

2、性能测试与优化

2.1、benchmark测试

  • 主要格式要求:
    1. Benchmark打头
    2. 不能有返回值
    3. 文件以_test.go结尾
// 文中全局有一个StrData变量,是一个200长度的字符串slice
// 间接应用“+”号拼接
func BenchmarkStringsAdd(b *testing.B) {
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        var s string
        for _, v := range StrData {
            s += v
        }
    }
    b.StopTimer()

}

2.2、优化策略

  • slice性能优化

    预分配容量在已有切片基础上创建切片,注意大内存未释放的陷阱。使用copy代替re-slice

  • map性能优化

    预分配内存

  • 字符串拼接处理

    使用 string.Builder

  • 使用空结构体

  • 需要原子计数时使用atomic原子工具包,而不是一味使用锁,因为锁是通过操作系统实现的,比较慢,原子计数通过硬件实现,比较简单。

2.3、性能调优工具pprof

真正分析时常用4种

  • CPU Profiling:CPU 分析,按照一定的频率采集所监听的应用程序 CPU(含寄存器)的使用情况,可确定应用程序在主动消耗 CPU 周期时花费时间的位置

  • Memory Profiling:内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前和历史内存使用情况,以及检查内存泄漏。

  • Block Profiling:阻塞分析,记录 goroutine 阻塞等待同步(包括定时器通道)的位置。

  • Mutex Profiling:互斥锁分析,报告互斥锁的竞争情况。