高质量编程
1. 简介
1.1 什么是高质量
各种边界条件是否考虑完备
异常情况处理,稳定性保证
易读易维护
1.2 编程原则
简单性、可读性、生产力
我认为高质量编程就要用简单的语言实现应有的功能,代码逻辑简单清晰,让他人可以读懂,可以提高团队的工作效率。
2. 编程规范
2.1 代码格式
推荐使用gofmt自动格式化代码
2.2 注释
注释符号//
注释应该解释代码作用,解释代码来源,解释代码实现的原因。
例如用go语言打印出九九乘法表
package main
import "fmt"
func main() {
// 外层循环控制被乘数 i,从 1 到 9
for i := 1; i <= 9; i++ {
// 内层循环控制乘数 j,从 1 到 i
for j := 1; j <= i; j++ {
// 打印乘法表达式,并使用 %2d 格式化保证对齐
fmt.Printf("%d * %d = %2d ", j, i, i*j)
}
// 换行符,打印下一行的乘法表达式
fmt.Println()
}
}
结果:
2.3 命名规范
- 包名:一般使用小写字母,不使用下划线或驼峰命名法。例如:"fmt", "net/http"。
- 变量和函数名:使用驼峰命名法,首个单词小写,后续单词首字母大写。例如:"myVariable", "calculateSum"。
- 常量名:使用全大写字母,单词间使用下划线分隔。例如:"PI", "MAX_VALUE"。
- 类型名:使用驼峰命名法,首字母大写。例如:"Person", "Employee"。
- 结构体字段:使用驼峰命名法,首字母小写。例如:"personName", "employeeAge"。
- 接口名:使用以 "er" 结尾的驼峰命名法,首字母大写。例如:"Reader", "Writer"。
- 文件名:使用全小写字母,可使用下划线分隔单词。例如:"my_file.go", "utils_test.go"。
此外,还有一些特殊的约定:
- 不推荐使用单字符变量名,除非是临时变量。
- 私有成员或私有函数使用以小写字母开头的驼峰命名法。例如:"privateField"。
- 导出的成员或函数使用以大写字母开头的驼峰命名法。例如:"ExportedField"。
这些命名规范符合 Go 语言社区的约定,能提升代码的可读性和一致性。但是记住,最重要的是选择一个命名规范,并保持一致性。
2.4 控制流程
避免嵌套,保持正常流程清晰
尽量保持正常代码路径为最小缩进
2.5 错误和异常处理
error尽可能提供简明的上下文信息链,方便定位问题
panic用于真正异常情况
recover生效范围,在当前goroutine的被defer的函数中生效
性能优化
1.Benchmark
go语言提供了支持基准性能测试的benchmark工具
例如:
import (
"fmt"
"testing"
)
func BenchmarkSprint(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
fmt.Sprint(i)
}
}
2.Slice
slice预分配内存
另一个大陷阱:大内存未释放
3.Map
map中保存值,而不是指针,使用分段map。
4.空结构化
使用struct{}优化
性能调优
1.简介
要依靠数据
要定位最大瓶颈
不要过早优化
不要过度优化
2.性能优化工具pprof
2.1 pprof关注的模块
- CPU profile:报告程序的 CPU 使用情况,按照一定频率去采集应用程序在 CPU 和寄存器上面的数据
- Memory Profile(Heap Profile):报告程序的内存使用情况
- Block Profiling:报告 goroutines 不在运行状态的情况,可以用来分析和查找死锁等性能瓶颈
- Goroutine Profiling:报告 goroutines 的使用情况,有哪些 goroutine,它们的调用关系是怎样的
2.2 引入方式
import "net/http/pprof"
import "runtime/pprof"
2.3 使用方式
如果使用了默认的 http.DefaultServeMux,只需要添加一行:
import _ "net/http/pprof"
如果应用使用了自定义的 Mux,则需要手动注册一些路由规则:
r.HandleFunc("/debug/pprof/", pprof.Index)
r.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
//等等