Go语言进阶 | 青训营笔记

76 阅读2分钟

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

GO 错误和异常处理

优先使用 errors.New 来创建匿名变量来直接表示该错误。有格式化需求时使用 fmt.Errorf
复杂错误(错误嵌套)在 fmt.Errorf 中使用 %w 关键字来将一个错误 wrap 至其错误链中

使用 errors.Is 可以判定错误链上的所有错误是否含有特定的错误
使用 errors.As 在错误链上获取特定种类的错误

error 尽可能提供简明的上下文信息链,方便定位问题

panic 一般不在业务逻辑中使用(如果当前 goroutine 中所有 deferred 函数都不包含 recover 就会造成整个程序崩溃)。用于真正异常(不能继续下去)的情况:当程序启动阶段发生不可逆转的错误时,可以在 init 或 main 函数中使用 panic
recover 生效范围:在当前goroutine的被defer的函数中



GO 性能优化建议

预分配内存 尽可能在 make() 创建切片(slice)、map 时提供初始容量信息(make([]int, 0, size)make(map[int]int, size)

切片的本质是一个数组片段的描述,包括:数组指针、片段的长度、片段的容量(不改变内存分配情况下的最大容量)
切片操作并不复制切片指向的元素
在已有切片基础上创建一个新的切片( 如 origin[len(origin)-2:] )会复用原切片的底层数组,如果只是要用一小部分,会导致大内存没有被释放
建议:make 一个新切片,再调用 copy 拷贝原切片的部分(用copy代替re-slice)


使用 strings.Builderbytes.Buffer 处理拼接字符串(两者也都可以预分配内存),不要直接用 +(字符串底层是不可变类型,占用内存大小固定,每次+ 都会重新分配内存)
strings.Builderbytes.Buffer 底层都是[]byte数组,内部维护了扩容策略
bytes.Buffer 转化为字符串重新申请了一块空间, strings.Builder 直接将底层的 []byte 转换为字符串类型返回


空结构体实例不占用内存空间,可作占位符
m := make(map[int]struct{}) 实现 Set


通过 atomic 包 维护原子变量
上锁是操作系统实现的,属于系统调用,sync.Mutex 一般用于保护一段逻辑
atomic 操作是通过硬件实现的
对于非数值系列,可以使用 atomic.Valueatomic.Value 能承载一个 interface{}



性能优化方向

  • 业务代码优化
  • SDK
  • 基础库
  • 语言运行时系统优化
  • OS