这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
Go语言高质量编程
一、高质量编程的原则
二、编码规范-代码格式
gofmt
gofmt是GO官方开发团队提供的一个工具,可以帮助开发者来格式化他们代码并统一风格。其实gofmt是一个程序,可以读取标准输入,看传入的是文件路径或者目录,并格式化该文件或该目录下的所有.go文件
gofmt的相关命令参数:
usage:gofmt[flags][path…]
-cpuprofile string
将CPU配置文件写入此文件
-d 显示差异而不是重写文件
-e 报告所有错误(如果不使用此标记,则只会打印每行的第1个错误且只打印前10个错误。)
-l 列出格式与gofmt不同的文件
-R 字符串
重写规则(例如“a[b:len(a)]->a[b:'')
-S 简化代码
-w 将结果写入(源)文件而不是stdout
-s简化代码
-
去除数组、切片、Map初始化时不必要的类型声明
如下形式的切片表达式: []T{T{}, T{}} 将被简化为: []T{{}, {}} -
去除数组切片操作时不必要的索引指定
如下形式的切片表达式: s[a:len(s)] 将被简化为: s[a:] -
去除迭代时非必要的变量赋值
如下形式的迭代: for x, _ = range v {...} 将被简化为: for x = range v {...} 如下形式的迭代: for _ = range v {...} 将被简化为: for range v {...}
go imports
goimports 也是GO官方开发团队提供的工具,可以对项目的依赖的包进行管理,会自动增删依赖的包引用、将依赖包按字母排序并分类。
小总结
使用规范的代码格式及统一的代码风格,可以极大的提升团队的开发效率,减少了因个人的差异化带来的不必要的麻烦
三、编码规范-注释
注释为代码的可读性提供了有效的保障
注释还应为代码提供适合解释代码的外部因素,在相应的场景下提供额外的上下文,以供其他程序猿理解
关于公共符号的注释
- 包中声明的每个公共符号:变量、常量、函数体以及结构体都需要添加注释
- 任何既不明显也不简短的公共功能必须予以注释
- 无论长度、复杂度如何,都必须对库中的函数加以注释
四、编码规范-命名
1.代码的命名
好的代码离不开好的命名
看如下的代码:
i和index仅在for循环里使用,且仅仅代表迭代的次数,index的额外冗长不不能提高代码的可读性
再看如下的代码:
很显然,deadline有明确的指示,而T可代表所有和time相关的,因此使用有特殊含义的命名对代码的可读性事关重要
2.包的命名
小总结
代码的命名的核心要素是降低读者理解代码的成本,要重点考虑上下文信息,一个好的命名必定是简洁清晰明了的。
五、编码规范-流程控制
1.避免嵌套
从最简单的if else 开始,如果两个分支都包含return语句,则可以去除冗余的else方便后续维护,else一般是正常的流程,如果在流程中还有新的判断逻辑,应该新增if判断,避免分支嵌套
2.尽量保持代码路径为最小缩进
- 优先处理特殊、错误情况,尽早返回或继续循环来避免嵌套
函数最后一行返回错误,必须追溯到最早匹配的左括号,才能了解何时会触发错误,如果中间的代码很长,这必然会增加阅读的成本和理解的成本。如果后续流程新增了新的判断逻辑或新的函数调用,则又是一层嵌套,代码可读性的降低是指数级变化的。
相比之前的代码,满足了优先处理错误情况的原则,可读性有了极大的提高。
小总结
- 线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支
- 正常的流程应沿着屏幕向下移动(避免反复横跳[狗头])
- 提升代码的可读性和可维护性
- 故障问题一般出现在复杂的条件或循环语句中
六、编码规范-错误处理
1.简单错误
2.错误链处理
3.错误判定
在错误链上要获取特定的错误,使用errors.As
4.panic
- 不建议在业务代码中使用panic(如果所有goroutine中所有defer中没有recover会造成程序崩溃)
- 如果问题可以被屏蔽或解决,建议用errors代替panic
- 当程序在启动阶段发生不可逆转的错误时,应在inti或main中使用panic
5.recover
- recover只在被defer的函数中使用
- 嵌套无效
- 只在当前goroutine生效
- defer后进先出
- 需要更多的上下文信息,可在recover后,在log中记录当前的栈
总结
高质量的代码依赖于高质量的命名、流程控制、注释、错误处理,写代码并不是跑起来就完事那么简单,要注重代码的可读性和可维护性(低耦合,高内聚),养成一个好的编码习惯是成为一名优秀程序猿的重中之重。