这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记
高质量编程
-
简单性、可读性、生产力
-
编码规范:编码规范本身就是为了统一编码形式,提高效率,除去代码风格上不同的规范有一定细微的差别,在注释,命名,流程控制等地方基本都是相通的
- Go 语言自带 fmt 自动格式化,可以统一代码格式
- 使用 Go mod 管理依赖
go mod init // 初始化 go mod tidy // 自动安装整理依赖 go get “url” // 获取依赖-
注释:在代码注释中,一般都会包含功能说明,公共符号说明等内容
- 注释应该解释代码作用
- 注释应该解释代码如何做的
- 公共符号始终要注释
- 注释应该解释代码实现的原因
- 注释应该解释代码什么情况会出错
-
命名规范:在命名中,大多采用驼峰命名法或者下划线分隔命名法,对于缩略词大写
- package:只由小写字母组成。不包含大写字母和下划线等字符
- function:函数名不携带包名的上下文信息,因为包名和函数名总是成对出现的
- variable:简洁胜于冗长,缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写
- 流程控制:在流程控制中,一般对于非正常返回逻辑的代码分支优先编写
- 异常处理
简单错误 :errors.New()
复杂错误 :Wrap 和 Unwarp 嵌套error
panic : panic 程序崩溃异常
-
优化建议
- 对于 slice,map 等预分配内存
- 在复用 slice 小片段时通过 copy 函数避免大内存无法释放
- 字符串处理通过 strings.Builder 优化效率
- map使用空结构体 实现set
- atomic包 代替互斥锁
- strings 使用 Grow() 预分配空间
- benchmark 工具
go test -bench=. -benchmembenchmark 是 Go 语言自带的基准测试工具,使用规则如下:
- 使用 _test.go 结尾
- 函数名 Benchmark 开头
- 唯一参数(b *testing.B)
- 使用循环,次数为 b.N
- 可以使用 b.ResetTimer 重置函数内计时器
func BenchmarkFib(b *testing.B) { // run the fib(5) function b.N times for n := 0; n < b.N; n++ { fib(5) } }go test -bench=. go test -bench=BenchmarkFib go test ./dir -bench=BenchmarkFib注意:如果不进入目录执行 test,就会找不到文件
性能调优实战
-
性能分析工具 pprof:
pprof 是用于可视化和分析性能分析数据的工具,需要配合 graphviz 使用
安装 graphviz 过程:
下载地址,安装后在系统路径(path)中加入 %bin% 地址,然后一定要重启 IDE,重启后即可使用 graphviz 查看图形化界面。
Go 语言带有 pprof 的依赖包,只需导入 net/http/pprof
使用以下代码监听
if err := http.ListenAndServe("localhost:6060", nil); err != nil { fmt.Printf("start pprof failed on %s\n", "localhost:6060") os.Exit(1) }只需执行以下语句即可显示各种资源使用的图形化界面
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap" # 内存 go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/cpu" # cpu go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine" # 协程 go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex" # 锁 go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block" # 阻塞