这是我参与「第三届青训营 -后端场」笔记创作活动的的第三篇笔记
主要内容:
- 如何编写更简洁清晰的代码
- 常用 Go 语言程序优化手段
- 熟悉 Go 程序性能分析工具
- 了解工程中性能优化的原则和流程
01 高质量编程
代码格式:gofmt,自带;goimport
注释
编码规范:
-
简洁胜于冗长
-
缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写
- 例如使用 ServeHTTP 而不是 Servehttp
- 使用 XMLHTTPRequest 或者 xmlHTTPRequest
-
变量距离其被使用的地方越远,则需要携带越多的上下文信息
-
全局变量在其名字中需要更多的上下文信息,使得在不同地方可以轻易辦认出其含义
-
package
- 只由小写字母组成。不包含大写字母和下划线等字符
- 简短并包含一定的上下文信息。例如 schema、 task等
- 不要与标准库同名。例如不要使用 sync 或者 strings
- 不使用常用变量名作为包名。例如使用 bufio 而不是 buf
- 使用单数而不是复数。例如使用 encoding 而不是 encodings
- 谨慎地使用缩写。例如使用 fmt 在不破坏上下文的情况下比 format 更加简短
-
控制流程避免嵌套;优先处理错误情况/特殊情况,尽早返回或继续循环
if err := doSomething(); err != nil { return err } return nil -
简单错误
- 简单的错误指的是仅出现一次的错误,且在其他地方不需要捕获该错误
- 优先使用
errors.New来创建匿名变量来直接表示简单错误 - 如果有格式化的需求,使用
fmt.Errorf
-
错误的 Wrap 和 Unwrap 使用
%w关键字关联错误至错误链return fmt.Errorf("xxx: %w", err)错误判定用
errors.is,不同于使用==,使用该方法可以判定错误链上的所有错误是否含有特定的错误if errors.Is(err, fs.ErrNotExist)使用
errors.As在错误链上获取特定种类的错误
性能优化:
BenchMark 基准性能测试工具
- silice 预分配内存: 尽可能在使用 make() 初始化切片时提供容量信息
- 陷阱—大内存未释放:已有切片基础上新建小切片,底层数组得不到释放。用copy代替re-slice
- map 预分配内存:提前分配好空间可以减少内存拷贝和 Rehash 的消耗
- 使用
strings.Builder拼接字符串 - 使用空结构体节省内存:例如用map实现Set,只需要key,可以将map的value类型设置为struct,因为即使是bool也要1个字节空间
- 使用
atomic包进行线程保护操作
02 性能调优实战
性能分析工具 pprof
采样-Sample
- CPU
- 堆内存-Heap
- 协程-Goroutine
介绍了采样过程和原理
案例
- 业务服务优化
- 基础库优化
- 编译器&运行时优化