ByteCamp - Note3

116 阅读2分钟

高质量编程

编码规范

错误和异常处理

Wrap和Unwrap
fmt.Errorf %w 生成错误链

错误判定
errors.Is 判断制定类型的错误 获取特定种类的错误,errors.As

panic
不建议在业务代码中使用,如果不包含recover回造成崩溃 若可以被屏蔽或解决,应当用error代替panic

recover
只在当前goroutine生效,只在被defer的函数使用
可以处理出panic的上下文

func (t *treeFS) Open(name string) (f fs.File, err error){
    defer func(){
        if e:= recover(); e != nil {
            f = nil
            // 记录下当前的调用栈
            err = fmt.Errorf("gifs panic: %v\n%s", e, debug.Stack())
        }
    }()
}

性能

Benchmark-性能优化建议

go test -bench=. -benchmem 运行时间、内存分配

slice

最好可以预分配,减少扩容开销,map同理

大内存未释放

在已有切片基础上创建切片,不会创建新底层数组

  • 如果原切片较大,代码在原切片基础上新建小切片,那么原底层数组在内存中有引用,得不到释放
  • 使用copy代替re-slice
func GetLastBySlice(origin []int) []int{
    return origin[len(origin)-2:]
}
func GetLastByCopy(origin []int) []int{
    res := make([]int, 2)
    copy(res, origin[len(origin-2):])
    return res
}

使用gotest测试go test -run=. -v

使用strings.Builder

string with + << bytes.Buffer < strings.Builder
每次+回重新分配内存,后者底层都是[]byte,维护扩容策略。bytes.Buffer 转换为字符串时重新申请了空间,strings.Builder直接将底层[]byte转换成字符串类型返回

使用空结构体

空结构体是一个占位符,不需要值,不占空间

  • 实现Set,可以考虑用Map代替

atomic

线程安全的计数器,比加锁性能好很多。锁由os实现,属于系统调用;atomic使用硬件实现,效率更高。

性能调优工具 - pprof

pprof实验blog blog.wolfogre.com/posts/go-pp…

定位瓶颈