Golang高质量编程与性能优化 | 青训营

92 阅读3分钟

1.高质量编程

1.1高质量编程的要求

  • 各种边界条件是否考虑完备
  • 异常情况处理,稳定性保证
  • 易读易维护

一般来说可以分成:简单性,可读性,生产力

Untitled.png

1.2 编码规范

1.2.1注释

保重声明的每个公共的符号(变量常量函数结构体)都要有相应的注释

任何既不明显也不简短的公共功能需要给注释

无论长度或复杂程度如何,库中的函数都需要给予注释

示例:

Untitled2.png

有一个例外:不需要注释实现接口的方法,只需要给一行以便联系上下文即可

注释的目标:

解释代码作用,适合注释公共符号

Untitled3.png

解释代码如何做到,适合解释实现过程

Untitled4.png

解释实现的原因,适合解释代码的外部因素,需要额外提供上下文

Untitled5.png

解释代码什么情况下会出错,适合解释代码的限制条件

Untitled6.png

代码是最好的注释

注释应该提供代码未提供的额外有效信息

1.2.2代码格式

推荐使用gofmt自动格式化代码

gofmt是Go官方提供的工具,能自动格式化代码为官方统一风格

1.2.3命名规范

变量命名:

简洁胜于冗长

缩略词全为大写,但当其位于变量开头且不需导出时,使用全小写

示例:ServerHTTP,xmlHTTPRequest

变量距离使用的地方越远,越要提供上下文信息

全局变量需要更多的上下文信息

Untitled7.png

函数命名:

函数名不携带包名的上下文信息

函数名尽量简短

当名为foo的包的的某个函数返回值为Foo类型时,可以省略类型

返回其他类型时,需要有在函数命中的类型信息

示例:

Untitled8.png

当调用方实际调用时,一般是直接写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

使用该方法可以判定错误链上的所有错误是否含有特定的错误

在错误链上获取特定类型的错误使用error.As

还可以使用panic进行错误处理

不建议在业务中使用panic

但是发生了无法逆转的错误的话可以用panic

recover:

recover只能在被defer的函数中使用

嵌套无法生效

只在当前goroutine生效

多个defer的顺序是后进先出

作用,如果需要更多的上下文信息,可以recover后在log记录当前的调用栈,调用debug.Stack()就可以将此信息打印出来