这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记。
编码规范
代码格式
gofmt:Go语言官方提供的格式化代码工具
goimports:Go语言官方提供的依赖包管理工具
注释
- 注释应该解释代码的作用
- 注释应该解释代码如何做的
- 注释应该解释代码实现的原因
- 注释应该解释代码什么情况会出错
- 公共符号始终要注释
命名规范
variable:
- 缩略词全大写,但其位于变量开头且不需要导出时全小写
- 变量距离被使用的地方越远,越需要携带更多的上下文信息
- 变量使用有特定含义的名词
函数名:
- 函数名不携带包名的上下文信息,尽量简短
- 当
foo包某个函数返回类型Foo时可省略类型信息,返回类型不是Foo时可以在函数名中加入类型信息 - 导出的函数大写字母开头,非导出的小写字母开头
package:(必须)只包含小写字母,简短,包含一定的上下文信息,不要与标准库同名,(尽量)不用常用变量名,使用单数,谨慎缩写。
控制流程
- 处理逻辑尽量走直线,避免嵌套
- 尽量保持正常代码路径为最小缩进,也就是说错误处理流程嵌套进控制流程中
错误和异常处理
简单错误:指仅出现一次的错误,优先使用errors.New创建匿名变量表示,如果有格式化需求使用fmt.Errorf,用%w将一个错误关联到错误链中。
错误判定:erros.Is判断错误链上所有错误是否含有特定的错误,errors.As在错误链上获取特定种类的错误。
panic:不可逆转的错误可以使用panic,不建议业务代码使用panic。
recover:recover只能在当前goroutine中被defer的函数中使用,嵌套无法生效,defer的顺序是后进先出。
性能优化
性能优化建议
- Benchmark:
go test -bench=. -benchmem - slice:尽量make初始化时提供容量信息,
copy替代re-slice - map:尽量预分配内存
- 使用
strings.Builder代替bytes.Buffer和+ - 使用空结构体做占位符
- 变量保护使用
atomic代替加锁
性能调优原则
- 依靠数据不要猜测
- 定位最大瓶颈
- 不要过早优化
- 不要过度优化
性能分析工具 pprof
测试用的项目:github.com/wolfogre/go…
go run main.c运行测试程序,浏览器输入http://localhost:6060/debug/pprof/进入pprof监控页面:
- CPU
首先用top命令查看:
CPU占用率达到了77.7%。
终端使用命令go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10",采集10秒的数据:
用top命令查看CPU占用情况:
看到老虎在吃的函数占用最多,用list定位代码:
哦嚯,有个空循环,注释掉这段代码。
- 内存
终端使用命令go tool pprof "http://localhost:6060/debug/pprof/heap",查看内存:
输入top:
老鼠偷掉了绝大多数内存,用list命令:
定位到代码,注释掉。
- 协程
终端使用命令go tool pprof "http://localhost:6060/debug/pprof/goroutine",一样使用top和list定位:
剩下的锁和阻塞一样的排查方法,同时如果觉得命令行不够直观,也可以调用UI界面:
go tool pprof -http=:8888 "http://localhost:6060/debug/pprof/goroutine"
根据提示安装graphviz:
sudo pacman -S graphviz
再次运行pprof:
或者也可以用UI打开pprof保存的文件:
go tool pprof -http localhost:8888 ~/pprof/pprof.main.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz