这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记。
高质量编程简介
编写的代码准确可靠、简洁清晰:简单、可读、生产力
- 边界条件考虑完备
- 异常情况处理
- 易读易维护
编码规范
代码格式
gofmt自动格式化代码
GO语言官方工具,能够自动格式化GO
goimports:gofmt + 依赖包管理
注释
注释该有的4个作用:
- 解释代码作用
- 解释代码如何做
- 解释代码实现的原因
- 解释代码什么情况下出错
公共符号始终要注释:
- 包中声明的每个公共符号:变量、常量、函数、结构都需要
- 不明显也不简短的公共功能
- 库中的任何函数
- 例外:不需要注释实现接口的方法,如下:
//Read implents the io.Reader interface
func (r *Filereader) Read(buf []byte) (int, error)
命名规范
变量:
- 简洁
- 缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写,例如使用
ServeHTTP
而不是ServeHttp
;使用XMLHTTPRequest
而不是xmlHTTPRequest
- 变量距离其被使用的地方越远,则需要携带越多的上下文信息
函数:
- 不携带包名的上下文信息
- 尽量简短
- 当名为 foo 的包某个函数返回类型 Foo 时,可以省略类型信息而不导致歧义
- 当名为 foo 的包某个函数返回类型 T 时(T 并不是 Foo),可以在函数名中加入类型信息
包:
- 只由小写字母组成
- 简短并包含一定的上下文信息,如
schema
、task
- 不要与标准库同名,如不要使用
schema
orstrings
控制流程
避免嵌套,保持正常流程清晰,如两个分支都包含return
,则可以去除冗余的else
尽量保持正常代码路径为最小缩进,优先处理错误情况/特殊情况,尽早返回或继续循环来减少嵌套
错误和异常处理
简单错误(仅出现一次的错误)
优先使用errors.New
来创建匿名变量来直接表示简单错误
如有格式化需求,使用fmt.Errorf
func defaultCheckRedirect(req *Request, via []*Request) error {
if len(via) >= 10 {
return errors.New("stopped after 10 redirects")
}
return nil
}
错误的Wrap和Unwrap
错误的Wrap实际上是提供了一个error嵌套另一个error的能力,从而生成一个error的跟踪链
在fmt.Errorf
中使用 %w
关键字来将一个错误关联至其错误链中
list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles"))
if err != nil {
return fmt.Errorf("reading srcfiles list: %w", err)
}
错误判定
判断一个错误是否为特定错误,使用errors.ls
该方法可以判定错误链上的所有错误是否含有特定错误
在错误链上获取特定种类的错误,使用errors.As
panic
用于真正异常情况
调用函数不包含 recover
会造成程序崩溃
recover
只能在被 defer 的函数中使用
嵌套无法生效
只在当前goroutine
生效
如果需要更多的上下文信息,可以recover
后在log
中记录当前的调用栈