这是我参与「第五届青训营 」笔记创作活动的第3天
1.本堂课重点内容
- 如何编写更简洁清晰的代码
- 常用Go语言程序优化手段
2.具体案例
3. 如何编写更简洁清晰的代码
3.1 高质量编程
3.1.1 简介
什么是高质量
编写的代码能够达到正确可靠、简洁清晰的目标可称之为高质量代码
- 各种边界条件是否考虑完备
- 异常情况处理,稳定性保证
- 易读易维护
3.1.2 编程原则
- 简单性
- 可读性
- 生产力
3.1.3 编码规范
- 代码格式
- 注释
- 命名规范
- 控制流程
- 错误和异常处理
代码格式
gofmt
Go 语言官方提供的工具,自动格式化Go语言代码为官方统一风格
goimports
管理依赖包、自动增删依赖的包引用
注释
- 包中声名的每个公共的符号:变量、常量、函数以及结构都需要添加注释
- 任何既不明显也不简短的公共功能必须予以注释
- 无论长度或复杂程度如何,对库中的任何函数都必须进行注释
例外 - 不需要注释实现接口的方法
命名
- 简介胜于冗长
- 缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写
控制
-
避免嵌套,保证正常流程清晰
eg:
if bool { return xx; } else { return xxx; } //优化 if bool { return xx; } return xxx; -
尽量保证正常代码路径为最小缩进 优先处理错误情况,尽早返回或继续循环来减少嵌套 eg:
func OneFunc() error{ err := doSomething() if err == nil{ err := doAnytherThing() if err == nil{ return nil } return err } return err } //优化 func OneFunc() error{ if err := doSomething(); err != nil{ return err } if err := doAnotherThing(); err != nil { return err } return nil }
错误和异常处理
-
简单错误
简单错误指的是仅出现一次的错误,且在其他地方不需要捕获该错误 优先使用errors.New来创建匿名变量来直接表示简单错误
return errors.New("This is a error")如果有格式化需求,使用fmt.Errorf
-
复杂错误
错误的Wrap实际上提供了一个error嵌套两一个error的能力,从而生成一个error的跟踪链
在fmt.Errorf中使用:w%关键字来将一个错误关联至错误链中 -
错误判定
判定一个错误是否为特定错误,使用errors.Is 不同于使用==,使用该方法可以判定错误链上的所有错误是否含有特定的错误 使用errors.As 可以把错误的内容取出来
-
panic 不建议在业务代码中使用panic 调用函数不包含recover会造成程序崩溃 若问题可以解决或被屏蔽,建议使用error代替panic
-
recover
生效范围: 在当前goroutine的被defer的函数中生效 嵌套无法生效 defer语句是后进先出
4. 常用Go语言程序优化手段
4.1 性能优化建议
- 性能优化的前提是满足正确可靠、简洁清晰等质量因素
- 性能优化是综合评估,有时侯时间效率和空间效率可能对立
- 针对go特性,介绍go相关的性能优化建议
4.2 Benchmark
- 性能表现需要实际数据衡量
- Go语言提供了支持基准性能测试的benchmark工具
go test -bench= . -benchmem
4.3 Slice预分配内存
- 尽可能在使用make()初始化切片时提供容量信息
- 在已有切片基础上创建切片,不会创建新的底层数组
- 使用copy代替re-slice
4.4字符串处理
- strings.Builder
- ByteBuffer
- 直接使用+号不推荐 性能最差
4.5 空结构体
- 空结构体struct{}实例不占据任何的内存空间
- 可作为各种场景下的占位符使用