这是我参与「第五届青训营 」伴学笔记创作活动的第3天。
今天的课我很爱。老师引导的很详细了。
1.编程规范(粗略)
是说我咋有印象,原来是这个资料呀
xxjwxc/uber_go_guide_cn: Uber Go 语言编码规范中文版. The Uber Go Style Guide . (github.com)
代码格式
- gofmt, goimports,用于格式化的小工具
- 而一般用的go fmt是在调用 gofmt 时添加了
-l -w参数,相当于执行了gofmt -l -w *.go
- goimports需要安装并编译
https://github.com/golang/tools.git,才能对包进行管理
注释
- 用于易于维护,让别人更容易读懂
- 应该解释代码作用,代码如何做的,代码实现的原因,代码什么情况会出错,
- 在代码上下文较远时,也需注释
- 除了实现接口的方法,对公共符号(大写首字母)的都需注释
命名规范
- 包名只能由小写字母组成,简短并包含一定上下文信息,不与标准库同名。尽量不用常用变量名,不用复数,谨慎缩写
- 文件名缩写统一大小写,公开的缩写单词都大写
- 函数名不携带包名的上下文信息,因为包名和函数名总是成对出现的
- 代码风格,减少缩进,减少嵌套,尽早返回,先判错误,
2.性能优化
工具
查看性能工具,Benchmark,见上篇介绍
性能分析工具,pprof
//用法 在 import 中添加 _ "net/http/pprof" 的引用
import (
_ "net/http/pprof"
)
//设置配置文件,测试运行时间10s
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
//然后top查看
(pprof) top
Showing nodes accounting for 4.45s, 96.74% of 4.60s total
Dropped 41 nodes (cum <= 0.02s)
Showing top 10 nodes out of 23
flat flat% sum% cum cum%
3.98s 86.52% 86.52% 4.06s 88.26% github.com/wolfogre/go-pprof-practice/animal/felidae/tiger.(*Tiger).Eat
0.27s 5.87% 92.39% 0.27s 5.87% runtime.stdcall3
0.08s 1.74% 94.13% 0.08s 1.74% runtime.asyncPreempt
0.06s 1.30% 95.43% 0.06s 1.30% runtime.stdcall6
0.03s 0.65% 96.09% 0.04s 0.87% runtime.(*pallocData).findScavengeCandidate
0.01s 0.22% 96.30% 0.03s 0.65% runtime.(*pageAlloc).scavengeReserve
0.01s 0.22% 96.52% 0.03s 0.65% runtime.runtimer
0.01s 0.22% 96.74% 0.28s 6.09% runtime.sysUnused
0 0% 96.74% 4.06s 88.26% github.com/wolfogre/go-pprof-practice/animal/felidae/tiger.(*Tiger).Live
0 0% 96.74% 4.07s 88.48% main.main
(pprof)
//精准定位
(pprof) list Eat
Total: 4.60s
ROUTINE ======================== github.com/wolfogre/go-pprof-practice/animal/felidae/tiger.(*Tiger).Eat in E:\GoProjects\src\go-pprof-practice\animal\felidae\tiger
\tiger.go
3.98s 4.06s (flat, cum) 88.26% of Total
. . 19:}
. . 20:
. . 21:func (t *Tiger) Eat() {
. . 22: log.Println(t.Name(), "eat")
. . 23: loop := 10000000000
3.98s 4.06s 24: for i := 0; i < loop; i++ {
. . 25: // do nothing
. . 26: }
. . 27:}
. . 28:
. . 29:func (t *Tiger) Drink() {
//进入可视化界面
(pprof)web
//注释掉tiger的Eat方法
(pprof) list Eat
Total: 20ms
(pprof) top
Showing nodes accounting for 20ms, 100% of 20ms total
Showing top 10 nodes out of 17
flat flat% sum% cum cum%
10ms 50.00% 50.00% 10ms 50.00% runtime.adjusttimers
10ms 50.00% 100% 10ms 50.00% runtime.heapBitsSetType
0 0% 100% 10ms 50.00% github.com/wolfogre/go-pprof-practice/animal/felidae/cat.(*Cat).Climb (inline)
0 0% 100% 10ms 50.00% github.com/wolfogre/go-pprof-practice/animal/felidae/cat.(*Cat).Live
0 0% 100% 10ms 50.00% log.(*Logger).Output
0 0% 100% 10ms 50.00% log.Println
0 0% 100% 10ms 50.00% main.main
0 0% 100% 10ms 50.00% runtime.Caller
0 0% 100% 10ms 50.00% runtime.CallersFrames (inline)
0 0% 100% 10ms 50.00% runtime.checkTimers
(pprof)
//重新执行,heap进入内存分析的有菜单项可视化窗口,换为其他参数可访问其他分析的可视化窗口
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
参数
flat 当前函数本身的执行耗时
flat% flat占CPU总时间的比例
sum%/% 上面每一行的flat%总和
cum 当前函数本身加上其调用函数的总耗时
cum%/% cum占CPU总时间的比例
flat==cum,函数中没有调用其他函数
flat==0,函数中只有其他函数的调用
优化措施
- 对于slice和map尽量根据实际需求提前预估好cap,预分配内存
- 对于原切片较大的需要其中的一部分,则新建一个切片进行copy,避免内存逃逸(切片操作时原切片和新切片共享底层数组,底层数组在内存有引用,得不到释放)
- 字符串处理,速度string.Builder>bytes.Buffer>+,若预分配内存更快
func PrestrBuilder(n int, str string) string {
var builder strings.Builder
//扩容
builder.Grow(n * len(str))
for i := 0; i < n; i++ {
builder.WriteString(str)
}
return builder.String()
}
-
使用空结构体节省内存,空结构体不占任何内存空间,作为占位符节省资源同时具有很强语义。因此用map实现set时往往将值设为空接口体,bool都会多占一个字节空间。
- 对于一个变量加锁使用atomic包(通过硬件实现)比加锁(通过操作系统实现,系统调用)效率高。加锁应用于保护一段逻辑。