Go语言编码规范| 青训营

130 阅读5分钟

在青训营学到Go语言编码规范,感觉这是一个十分有用的基本功,因此在这写一篇文章来加深我对这一块的理解

编写的代码能够达到正确可靠、简洁清晰的目标可称之为高质量代码,一般需要满足以下几点:

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

我们应需要遵循的编程原则:

  1. 简单性
  • 消除“多余的复杂性”,以简单清晰的逻辑编写代码
  • 不理解的代码无法修复改进
  1. 可读性
  • 写出来的代码能保证别人能看懂,自己写的代码日后也能看懂
  • 常有自己写的shit mountain 代码放久了自己看不懂
  1. 生产力
  • 团队整体工作效率非常重要

编码规范

gofmt

gofmt是Go语言官方提供的工具,能自动格式化Go语言代码为官方的统一风格, goimorts也是Go语言官方提供的工具,实际等于gofmt加上依赖包管理,它能自动增删依赖的包引用、将依赖包按字母顺序排序并分类

Jet Brain的 GoLand就支持简单方便地配置:在偏好设置preference——Tools——actions on save 勾选 Reformat code 和 Optimize imports即可使你在保存你的Go文件时可以自动格式化你的代码,如下图

image.png

注释

  • 注释应该解释代码的作用(函数作用、函数参数含义)
  • 注释应该解释代码如何做的(该段函数做了什么事情)
  • 注释应该解释代码实现的原因(解释代码的外部因素,提供额外上下文)
  • 注释应该解释代码什么情况会出错
  • 注释多多益善
  • 尽量使代码本身包含注释信息(命名时使用全称或者公认的缩写)

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"

控制流程

  • 尽量减少嵌套
  • 尽量保持正常代码的为最小缩进