在青训营学到Go语言编码规范,感觉这是一个十分有用的基本功,因此在这写一篇文章来加深我对这一块的理解
编写的代码能够达到正确可靠、简洁清晰的目标可称之为高质量代码,一般需要满足以下几点:
- 各种边界条件是否考虑完备
- 异常处理情况,稳定性保证
- 易读易维护
我们应需要遵循的编程原则:
- 简单性
- 消除“多余的复杂性”,以简单清晰的逻辑编写代码
- 不理解的代码无法修复改进
- 可读性
- 写出来的代码能保证别人能看懂,自己写的代码日后也能看懂
- 常有自己写的shit mountain 代码放久了自己看不懂
- 生产力
- 团队整体工作效率非常重要
编码规范
gofmt
gofmt是Go语言官方提供的工具,能自动格式化Go语言代码为官方的统一风格, goimorts也是Go语言官方提供的工具,实际等于gofmt加上依赖包管理,它能自动增删依赖的包引用、将依赖包按字母顺序排序并分类
Jet Brain的 GoLand就支持简单方便地配置:在偏好设置preference——Tools——actions on save 勾选 Reformat code 和 Optimize imports即可使你在保存你的Go文件时可以自动格式化你的代码,如下图
注释
- 注释应该解释代码的作用(函数作用、函数参数含义)
- 注释应该解释代码如何做的(该段函数做了什么事情)
- 注释应该解释代码实现的原因(解释代码的外部因素,提供额外上下文)
- 注释应该解释代码什么情况会出错
- 注释多多益善
- 尽量使代码本身包含注释信息(命名时使用全称或者公认的缩写)
1. 包注释
每个包都应该有一个包注释,一个位于package子句之前的块注释或行注释。包如果有多个go文件,只需要出现在一个go文件中(一般是和包同名的文件)即可。 包注释应该包含下面基本信息(请严格按照这个顺序,简介,创建人,创建时间):
- 包的基本简介(包名,简介)
- 创建者,格式: 创建人: rtx 名
- 创建时间,格式:创建时间: yyyyMMdd
例如 util 包的注释示例如下
// util 包, 该包包含了项目共用的一些常量,封装了项目中一些共用函数。
// 创建人: hanru
// 创建时间: 20190419
2. 结构体/接口注释
每个自定义的结构体或者接口都应该有注释说明,该注释对结构进行简要介绍,放在结构体定义的前一行,格式为: 结构体名, 结构体说明。同时结构体内的每个成员变量都要有说明,该说明放在成员变量的后面(注意对齐),实例如下:
// User , 用户对象,定义了用户的基础信息
type User struct{
Username string // 用户名
Email string // 邮箱
}
3. 函数/方法注释
每个函数,或者方法(结构体或者接口下的函数称为方法)都应该有注释说明,函数的注释应该包括三个方面(严格按照此顺序撰写):
- 简要说明,格式说明:以函数名开头,“,”分隔说明部分
- 参数列表:每行一个参数,参数名开头,“,”分隔说明部分
- 返回值: 每行一个返回值
示例如下:
// NewtAttrModel , 属性数据层操作类的工厂方法
// 参数:
// ctx : 上下文信息
// 返回值:
// 属性操作类指针
func NewAttrModel(ctx *common.Context) *AttrModel {
}
命名规范
- 变量命名中,缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写
- 如使用ServeHTTP而不是ServeHttp
- 使用XMLHTTPRequest或者xmlHTTPRequest
- 变量距离其被使用的地方越远,则需要携带越多的上下文信息
- 全局变量在其名字中需要更多的上下文信息,使得在不同地方可以轻易辨认出其含义
- 函数名尽量简短,不携带包名的上下文信息
1. 包名
包名只由小写字母组成,没有大写字母和下划线
保持package的名字和目录保持一致,尽量采取有意义的包名,简短,有意义,尽量和标准库不要冲突。包名应该为小写单词,不要使用下划线或者混合大小写。
package demo
package main
2. 文件命名
尽量采取有意义的文件名,简短,有意义,应该为小写单词,使用下划线分隔各个单词。
my_test.go
3. 结构体命名
驼峰命名法(每个单词首字母大写,小驼峰就是首个单词首字母小写,大驼峰反之),一般采用大驼峰命名法,字母根据访问控制大写或者小写。
type FileHeader struct {
Filename string
Header textproto.MIMEHeader
Size int64
// contains filtered or unexported fields
}
4. 接口命名
命名方式与结构体相同采用驼峰命名法,单个函数的结构名以 “er” 作为后缀,例如 Reader , Writer 。
type Reader interface {
Read(p []byte) (n int, err error)
}
5. 变量命名
采用驼峰命名法,但有特殊情况:
- 如果变量为私有,且特有名词为首个单词,则使用小写,如 apiClient
- 其它情况都应当使用该名词原有的写法,如 APIClient、repoID、UserID
- 错误示例:UrlArray,应该写成 urlArray 或者 URLArray
- 若变量类型为 bool 类型,则名称应以 Has, Is, Can 或 Allow 开头,如下:
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool
6. 函数名命名
采用大驼峰命名法
func (c *Context) MultipartForm() (*multipart.Form, error) {
err := c.Request.ParseMultipartForm(c.engine.MaxMultipartMemory)
return c.Request.MultipartForm, err
}
7. 常量命名
全大写,下划线连接
const APP_VER = "1.0"
控制流程
- 尽量减少嵌套
- 尽量保持正常代码的为最小缩进