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

58 阅读3分钟

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

编码规范

错误和异常处理

简单错误

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

错误的 Wrap 和 Unwrap

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

错误判定

在错误链上获取特定种类的错误,使用errors.As

panic

  1. 不建议在业务代码中使用
  2. panic调用函数不包含 recover 会造成程序崩溃
  3. 若问题可以被屏蔽或解决,建议使用error 代替 panic
  4. 当程序启动阶段发生不可逆转的错误时可以在 init 或 main 函数中使用 panic

recover

  1. recover 只能在被 defer 的函数中使用
  2. 嵌套无法生效
  3. 只在当前 goroutine 生效
  4. defer 的语句是后进先出

Benchmark

benchmark结果说明
BenchmarkFib10-8-8表示GOMAXPROCS的值
1855870表示一共执行的次数,即b.N的值
602.5 ns/op每次执行花费的时间
0 B/op每次执行申请多大的内存
0 allocs/op每次执行申请几次内存

slice

在已有切片基础上创建切片,不会创建新的底层数组 可使用copy代替

set

可以考虑用map实现set map设置为空结构体

func EmptyStructMap(n int) {
    m := make(map[int]struct{})
}

atomic

  1. 锁的实现是通过操作系统来实现,属于系统调用
  2. atomic 操作是通过硬件实现,效率比锁高
  3. sync.Mutex 应该用来保护一段逻辑,不仅仅用于保护一个变量
  4. 对于非数值操作,可以使用 atomic.Value,能承载一个 interfaced
type atomicCounter struct {
    i int32
}
func AtomicAddOne(c *atomicCounter){
    atomic.AddInt32(&c.i, 1)
}
​
type mutexCounter struct {
    i int32
    m sync.Mutex
}
​
func MuteAddOne(c *mutexCounter) {
    c.m.Lock()
    c.i++
    c.m.Unlock()
}

pprof

常用命令

localhost:6060:/debug/pprof/
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"

top

label介绍
flat当前函数本身的执行耗时
flat%flat占CPU总时间的比例
sum%上面每一行的flat%总和
cum指当前函数本身加上其调用函数的总耗时
cum%cum占CPU总时间的比例

flat == Cum, 函数中没有调用其他函数

Flat == 0, 函数中只有其他函数的调用

heap 堆内存

采样原理

CPU

  1. 采样对象:函数调用和它们占用的时间
  2. 采样率: 100次/秒,固定值
  3. 采样时间: 从手动启动到手动结束

Heap-堆内存

  1. 采样程序通过内存分配器在堆上分配和释放的内存,记录分配/释放的大小和数量
  2. 采样率:每分配512KB记录一次,可在运行开头修改,1为每次分配均记录
  3. 采样时间:从程序运行开始到采样时
  4. 采样指标: alloc_space, alloc_objects,inuse_space,inuse_objects
  5. 计算方式: inuse = alloc - free

Goroutine-协程 & ThreadCreate-线程创建

  1. Goroutine 记录所有用户发起且在运行中的 goroutine (即入口非runtime开头的) runtime.main 的调用栈信息
  2. ThreadCreate 记录程序创建的所有系统线程的信息

Block-阻塞 & Mutex-锁

  1. 阻塞操作 采样阻塞操作的次数和耗时 采样率:阻塞耗时超过闽值的才会被记录,1为每次阻塞均记录
  2. 锁竞争 采样争抢锁的次数和耗时 采样率:只记录固定比例的锁操作,1为每次加锁均记录

Reference

  1. blog.wolfogre.com/posts/go-pp…
  2. juejin.cn/course/byte…