day3 go语言高质量编程和性能调优回顾 | 青训营笔记

55 阅读2分钟

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

1 Go高质量编程

1.1 高质量定义

-边界条件是否完备

-维护性,可读性,可读性

-异常情况处理

1.2 规范-注释

公共符号始终要注释

注释应该接受代码作用,如何做,实现的原因

1.3 规范-命名

-避免冗长的表达,比如说for循环中,内部变量简洁表达即可

-给外界调用的函数,通过参数名命名来实现更好的理解

1.4 规范-控制流程

-避免嵌套

-保持正常代码路径为最小路径(本质还是减少嵌套

1.5 规范-错误处理

-简单错误:err.new() 一次调用即可

-复杂错误: 错误链,fmt.Errorf中使用:%w关键字来将一个错误wrap至其错误链中

-错误判定: 除了 '==' 外,可以使用 errors.Is以及error.As 后者相比于前者在于AS会调取出指定类型的错误,并将错误赋值给定义好的变量,便于后续处理

-panic: 不建议在业务中直接使用,用于正真异常的情况

-recover: 只能在被defer中的函数使用,只在当前goroutien生效

2 性能调优

2.1 Benchmark

了解一下用法即可

2.2 Slice

-slice预分配内存:尽可能在使用make()初始化切片提供容量信息!(这个确实以前没注意过),原因是不提前确认容量信息的情况下,在append时容量不够的情况下,slice会发生内存的拷贝。

-大内存未释放:原切片较大时候,代码可能在原切片基础上新建小切片,导致原底层数组在内存中有引用,得不到释放,这个时候可以使用copy代替re-slice

2.3 Map

-map预分配内存:提前分配好空间,减少内存拷贝和Rehash的消耗

2.4 字符串处理

-使用string.Builder代替常规的+字符串拼接

func ByteBuffer(n int,str string) string{
    buf :=new(bytes.Buffer)
    for i:=0;i<n;i++{
        buf.WriteString(str)
    
    }
    return buf.String()
}
复制代码

原因:拼接每次都会重新分配内存,stringbuilder本质是[]byte数组

string.Builder也有预分配,builder.Grow

2.5 空结构体

使用空结构体节省内存

空结构体不占据任何的内存空间,可以作为各种场景下的占位符使用。

举例:假如我们需要一个set,仅仅对key进行操作,那么就可以定义成m1这种方式,相比于m2更省空间。

m1:=make(map[int]struct{})
m2:=make(map[int]bool)


2.6 Atomici包

锁的实现是通过操作系统来完成的,属于系统调用

atomic包则是通过硬件实现,实现效率比锁要高

3 性能调优

3.1 原则

3.2 pprof

一个性能调优工具

直接上实战

-启动项目后登入:http://localhost:6060/debug/pprof/