高质量编程及编码规范 | 青训营

97 阅读3分钟

1.1 高质量编程

  • 简单性
  • 可读性
  • 生产力

1.2 编码规范

1.2.1 代码格式

  • gofmt: go语言官方工具,自动格式化代码为官方统一风格
  • goimports: gofmt + 依赖包管理(自动增删依赖包 + 按字母表排序)

1.2.2 注释

  • 公共符号需要注释

  • 注释应该解释: 代码作用、代码如何做的、代码实现的原因、代码什么情况会出错
    代码是最好的注释 注释应提供代码未能提供的上下文信息

1.2.3 命名规范

variable

简洁胜于冗长
缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写
正:ServeHTTP、XMLHTTPRequest、xmlHTTPRequest
误:ServeHttp
变量距离其被使用的地方越远,则名称需要携带越多的上下文信息

function

函数名不需要携带包名的上下文信息,因为包名和函数名总是成对出现
函数名尽量简短
当名为foo的包某个函数返回类型Foo时,可以省略类型信息而不导致歧义
当名为foo的包某个函数返回类型T时,可以在函数名中加入类型信息

package

只由小写字母组成。不包含大写字母和下划线等字符
简短并包含一定的上下文信息。如schema、task
不要与标准库同名。例如不要使用sync或strings

以下规则尽量满足,以标准库包名为例:
不使用常用变量名为包名。如用bufio而不是buf
使用单数而不是负数。如用encoding而不是encodings
谨慎地使用缩写。如使用fmt比format更简短

小结

核心:降低阅读理解代码的成本
重点考虑上下文信息,设计简洁清晰的名称

1.2.4 控制流程

  • 避免嵌套,保持正常流程清晰
// Bad 
if foo {
	return x
}
else {
	return nil
}

// Good
if foo {
	return x
}
return nil
  • 尽量保持正常代码路径为最小缩进
    优先处理错误/特殊情况,尽早返回或继续循环来减少嵌套

小结

线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支
正常流程代码沿着屏幕向下移动
提升代码可维护性和可读性
故障问题多出现在复杂的条件语句和循环语句中

1.2.5 错误和异常处理

简单错误:

优先使用errors.New创建匿名变量来直接表示
若有格式化需求,使用fmt.Errorf

错误的Wrap和Unwrap

错误的Wrap实际上是提供了一个error嵌套另一个error的能力,从而生成一个error的跟踪链
在fmt.Errorf中使用:%w关键字来将一个错误关联至错误链中

错误判定

在错误链上获取特定种类的错误,使用errors.As

panic

不建议在业务代码中使用
调用函数不包含recover会造成程序崩溃

recover

只能在被的defer的函数中使用
嵌套无法生效
只在当前goroutine生效
defer语句后进先出

小结

error尽可能提供简明的上下文信息链,方便定位问题
panic用于真正异常的情况
recover生效范围,在当前rgoroutine的被defer的函数中生效