-
高质量编程\
-
编码规范\
-
代码格式\
- go fmt格式化代码\
- 提升可读性,风格一致的代码更容易维护、需要更少的学习成本、团队合作成本,同时可以降低 Review 成本\
-
注释\
- 解释代码作用\
- 解释代码如何做的\
- 解释代码实现的原因\
- 解释代码什么情况会出错\
- 公共符号始终要注释\
-
命名规范\
-
变量\
- 简洁胜于冗长\
- 缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写\
- 变量距离其被使用的地方越远,则需要携带越多的上下文信息\
- 全局变量在其名字中需要更多的上下文信息,使得在不同地方可以轻易辨认出其含义\
-
函数\
- 函数名不携带包名的上下文信息,因为包名和函数名总是成对出现的\
- 函数名尽量简短\
- 当名为 foo 的包某个函数返回类型 Foo 时,可以省略类型信息而不导致歧义\
- 当名为 foo 的包某个函数返回类型 T 时(T 并不是 Foo),可以在函数名中加入类型信息\
-
包\
- 只由小写字母组成。不包含大写字母和下划线等字符\
- 简短并包含一定的上下文信息。例如 schema、task 等\
- 不要与标准库同名。例如不要使用 sync 或者 strings\
-
-
控制流程\
- 避免嵌套\
- 优先处理错误情况\
- 如果两个分支中都包含 return 语句,则可以去除冗余的 else\
-
错误和异常处理\
-
简单错误\
- 只出现一次,且在其他地方不需要捕获\
- errors.New()\
- 如果有格式化需求则使用fmt.Errorf()\
-
错误的wrap和unwrap\
- 提供了一个error嵌套另一个error的能力,形成一个error的跟踪链\
- 在fmt.Errorf()中使用%w关键字将一个error关联至error链中\
-
panic\
- 不推荐在业务中使用panic\
- 建议使用error代替panic\
-
recover\
- 只能在被derfer的函数中使用\
- 嵌套无法生效\
- 只在当前goroutine生效\
- defer语句先进后出\
-
-
-
-
性能调优实战\
-
如何使用\
-
基准性能测试的Benchmark工具\
-
添加函数\
- func fib(x int) int {}\
-
生成fib函数test.go\
- func BenchmarkFib(b *testing.B) {}\
- go test -bench .\
-
-
-
建议\
-
slice\
- 尽可能在make初始化时指定容量信息\
- 扩容时有性能消耗\
-
map\
- 尽可能在make初始化时指定容量信息\
- 扩容时有性能消耗\
-
字符串处理\
-
拼接\
-
+\
- 性能最差\
-
strings.Builder\
- 性能与buffer差不多\
-
bytes.Buffer\
- 更快\
-
-
-
使用空结构体节省内存\
- 空结构体struct{}实例不占据内存空间\
- 可作为各种场景下的占位符使用\
-
atomic包\
-
性能比使用锁lock性能高\
- 锁是通过操作系统实现\
- atomic通过硬件实现\
-
-
-
原则\
- 要依靠数据不是猜测\
- 要定位最大瓶颈而不是细枝末节\
- 不要过早优化\
- 不要过度优化\
-
性能分析工具pprof\
-
排查实战\
- cpu\
- heap\
- goroutine\
-
采样过程和原理\
-
cpu\
-
采样对象\
- 函数调用和它们占用的时间\
-
采样率\
- 100次/秒\
-
采样时间\
- 手动开始到手动结束\
-
- heap 内存\
- goroutine\
- 阻塞和锁\
-
-
-