这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记
一.什么是高质量:编写的代码能够达到正确可靠,简明清晰的目标
其中要注意:考虑完备各种边界条件;做到异常情况处理和稳定性保证;易读易维护
二.如何高质量编写go代码
1.代码格式:
使用go语言官方提供的工具gofmt,可以自动格式化go语言代码为官方统一风格也可以使用go语言官方提供的goimports,自动增删依赖的包的引用,并将依赖包按照字母排序分类
2.注释
注释必须做到:解释代码作用;解释代码如何去做;解释代码实现原因;解释代码在什么情况下会出错
3.命名规范
(1).简洁 例如:for循环中的变量不需要过长
for i := 0; i < len(intArr); i++ {
intArr[i] = rand.Intn(100)
}
(2).缩略词全大写,但是当其位于变量开头且不需要到处时,使用全小写
(3).变量距离其被使用的地方越远则需要携带越多的上下文信息
(4).函数名尽量不携带报名的上下文信息
(5).包名只有小写字母,不包含大写字母和下划线等信息。不能与标准库同名。
4.流程控制
1.避免嵌套
if aaa{ if aaa {
return 1 return 1
}else{ =======> }
return 2 return 2
}
这样就避免了else的使用
2.尽量保持代码路径为最小缩进
for i := 0; i < len(score); i++ {
fmt.Printf("请输入第%d个元素", i+1)
fmt.Scanln(&score[i])
}
for i := 0; i < len(score); i++ {
fmt.Println(score[i])
}
for index, value := range score {
fmt.Printf("i=%v v=%v", index, value)
}
for i, v := range score {
fmt.Printf("i=%v v=%v", i, v)
}
5.错误和异常处理
1.简单错误:指仅出现一次的错误,在其他地方不需要捕获该错误
(1).使用errors.New创建匿名变量来直接表示简单错误
if a>=5 {
return errors.New("error")
}
(2).使用fmt.Errorf(会进行一次格式化)
if a == 0 {
// 将参数进行一次格式化,格式化后的字符串放入 error 中
return fmt.Errorf("数据 %d 不合法", a), 0
}
2.错误的Wrap和Unwrap
Wrap为我们提供了,可以一个error嵌套另一个error功能,我们可以根据嵌套的error序列,生成一个error错误跟踪链,也可以理解为错误堆栈信息,便于我们跟踪调试
a := errors.New("原始错误a")
b := fmt.Errorf("Wrap了一个错误%w", a)
3.错误判定:使用errors.Is来判断一个错误是否为特定错误,该方法可以判断错误链上所有的错误是否含有特定的错误
if errors.Is(err, ErrFoo) {
return 0, fmt.Errorf("tragedy: %w", err)
}
用errors.As来获取特定种类的错误
if errors.As(err, &bar) {}
注: errors.Is 和 errors.As 会尝试以递归的方式解包错误来找到匹配项
- recover:此函数只能在defer的函数中使用且嵌套无法生效recover() 方法调用后,会捕获到当前抛出的异常,并进行返回,如果没有异常,则返回 nil。
三.性能优化
1.使用Benchmark工具
2.slice预分配内存,尽可能在使用make()初始化时提供容量信息
一个切片由3部分组成:指针、长度和容量。指针指向底层数组,长度代表slice当前的长度,容量代表底层数组的长度
func PreAlloc(size int){
data := make([]int,0,size)
for k := 0; k < size; k++ {
data=append(data,k )
}
3.map预分配内存
func PreAlloc(size int){
data := make(map[int]int,size)
for k := 0; k < size; k++ {
data[k]=1
}
4.字符串处理
字符串拼接建议使用string.Builder
5.使用空结构体节省内存
6.atomic包
type mutexCounter struct{
i int32
m sync.Mutex
}
func MutexAddOne(c*mutexCounter){
c.m.Lock()
c.i++
c.m.Unlock()
}