1.高质量编程
1.1高质量编程的要求
- 各种边界条件是否考虑完备
- 异常情况处理,稳定性保证
- 易读易维护
一般来说可以分成:简单性,可读性,生产力
1.2 编码规范
1.2.1注释
保重声明的每个公共的符号(变量常量函数结构体)都要有相应的注释
任何既不明显也不简短的公共功能需要给注释
无论长度或复杂程度如何,库中的函数都需要给予注释
示例:
有一个例外:不需要注释实现接口的方法,只需要给一行以便联系上下文即可
注释的目标:
解释代码作用,适合注释公共符号
解释代码如何做到,适合解释实现过程
解释实现的原因,适合解释代码的外部因素,需要额外提供上下文
解释代码什么情况下会出错,适合解释代码的限制条件
代码是最好的注释
注释应该提供代码未提供的额外有效信息
1.2.2代码格式
推荐使用gofmt自动格式化代码
gofmt是Go官方提供的工具,能自动格式化代码为官方统一风格
1.2.3命名规范
变量命名:
简洁胜于冗长
缩略词全为大写,但当其位于变量开头且不需导出时,使用全小写
示例:ServerHTTP,xmlHTTPRequest
变量距离使用的地方越远,越要提供上下文信息
全局变量需要更多的上下文信息
函数命名:
函数名不携带包名的上下文信息
函数名尽量简短
当名为foo的包的的某个函数返回值为Foo类型时,可以省略类型
返回其他类型时,需要有在函数命中的类型信息
示例:
当调用方实际调用时,一般是直接写http.Serve(),所以我们可以使用上面的命名方式
package:
包名只有小写字母不含大写字母和下划线等字符
简短并包含一定的上下文信息:schema,task
不要与标准库同名
以下规则尽量满足:
不使用常用变量名作为包名:bufio not buf
使用单数而不是复数:encoding not encodings
谨慎的使用缩写:fmt
1.2.4 流程控制
避免嵌套,保持正常流程清晰
例如:如果两个分支都包含return,则可以省略冗余的else
if err!=nil{
fmt.Println(err)
return
}
return nil
//将后面的else省去了
尽量保持正常代码路径为最小缩进
优先处理特殊/错误情况,尽早返回或继续循环来减少嵌套
if err:=doSometing();err!=nil{
return err
}
if err=doAnotherThing();err!=nil{
return err
}
return nil
//将if条件判断与变量声明写在一处,减少缩进
尽量减少复杂的嵌套分支,处理逻辑走直线
1.2.5错误和异常处理
简单错误:
是指仅出现一次的错误,在其他地方也不需要捕获
使用errors.New()来创建匿名变量
如果有格式化需求使用fmt.ErrorOf
错误的Wrap和Unwrap:
实际上是提供了一个error嵌套另一个error的能力,实现了错误的跟踪链
在fmt.ErrorOf中使用%w关键字将一个错误关联至另一个错误链中
return fmt.Errorof("reading srcfiles list:%w",err)
//这样的话err现在就是一个错误链
判定一个错误是否为特定错误,使用error.Is
使用该方法可以判定错误链上的所有错误是否含有特定的错误
还可以使用panic进行错误处理
不建议在业务中使用panic
但是发生了无法逆转的错误的话可以用panic
recover:
recover只能在被defer的函数中使用
嵌套无法生效
只在当前goroutine生效
多个defer的顺序是后进先出
作用,如果需要更多的上下文信息,可以recover后在log记录当前的调用栈,调用debug.Stack()就可以将此信息打印出来