-
编程原则:简单性、可读性、生产力
-
代码格式:gofmt/goimports
-
注释:
- 注释应该解释代码作用:适合注释公共符号
- 注释应该解释代码如何做的:适合注释实现过程
- 注释应该解释代码实现的原因:适合解释代码的外部因素,提供额外上下文
- 注释应该解释代码什么情况会出错:适合解释代码的限制条件
- 公共符号始终要注释
- 包中声明的每个公共符号:变量、常量、函数以及结构都需要添加注释
- 任何即不明显也不简短的公共功能必须予以注释
- 无论长度或复杂程度如何,对库中任何函数都必须注释
-
命名规范
核心目标是降低阅读理解代码的成本,重点考虑上下文信息,设计简洁清晰的名称
- 变量:能看明白的地方简写,有需要语义信息的地方写全
- 函数:
- 函数名不携带包名的上下文信息,因为包名和函数名总是成对出现
- 函数名尽量简短
- 当名为 foo 的包某个函数返回类型为 Foo 时,可以省略类型信息而不导致歧义
- 当名为 foo 的包某个函数返回类型 T 时(T 不是 Foo),可以在函数名中加入类型信息
- 包:
- 仅有小写字母组成
- 简短并包含异地过年的上下文信息
- 不要与标准库同名
- 不使用常用变量名作为包名
- 使用单数而不是附属
- 谨慎地使用缩写
-
控制流程
- 避免嵌套,保持正流程清晰
- 尽量保持正常代码路径为最小缩进:有限处理错误/特殊情况,减少嵌套
-
错误和异常处理
- 简单错误(仅出现一次且在其他地方不需要捕获)
- 优先使用
errors.New
来创建匿名变量来直接表示简单错误 - 如果有格式化需求,使用
fmt.Errof
- 优先使用
- 错误的 Wrap 和 Unwrap
- 错误的 Wrap 提供了一个 error 嵌套另一个 error 的能力,从而生成一个 error 的跟踪链
- 在
fat.Errof
中使用%w
关键字来将一个错误关联至错误链中(Go1.13 默认可用)
- 错误判定:
- 检测错误链上是否含有特定的错误:
errors.Is
, - 在错误链上获取特定种类的错误:
errors.As
- 检测错误链上是否含有特定的错误:
- Panic
- 不建议在业务代码中使用
- 调用函数不包含
recover
会造成程序崩溃 - 若问题可以背屏蔽或解决,建议使用 error 代替
- 当程序启动阶段发生不可逆转的错误时,可以在 init 或 main 函数中使用
- recover
- 只能在被 defer 的函数中使用
- 嵌套无法生效
- 只在当前 goroutine 生效
- defer 语句是后进先出
- 如果需要更多的上下文信息,可 recover 后在 log 中记录当前的调用栈
debug.Stack()
- 简单错误(仅出现一次且在其他地方不需要捕获)