Go项目开发规范

命名规范

  • 需要注释来补充的命名就不算是好命名。
  • 使用可搜索的名称:单字母名称和数字常量很难从一大堆文字中搜索出来。单字母名称仅适用于短方法中的本地变量,名称长短应与其作用域相对应。若变量或常量可能在代码中多处使用,则应赋其以便于搜索的名称。
  • 做有意义的区分:Product和ProductInfo和ProductData没有区别,NameString和Name没有区别,要区分名称,就要以读者能鉴别不同之处的方式来区分

[TOC]

文件名命名规范

用小写,尽量见名思义,看见文件名就可以知道这个文件下的大概内容,对于源代码里的文件,文件名要很好的代表了一个模块实现的功能。

包名命名

包名应该为小写单词,不要使用下划线或者混合大小写.

接口命名

单个函数的接口名以”er”作为后缀,如Reader,Writer。接口的实现则去掉“er”。

1
2
3
type Reader interface {
        Read(p []byte) (n int, err error)
}

两个函数的接口名综合两个函数名

1
2
3
4
type WriteFlusher interface {
    Write([]byte) (int, error)
    Flush() error
}

三个以上函数的接口名,类似于结构体名

1
2
3
4
5
type Car interface {
    Start([]byte) 
    Stop() error
    Recover()
}

结构体命名

结构体名应该是名词或名词短语,如Custome、WikiPage、Account、AddressParser,避免使用Manager、Processor、Data、Info、这样的类名,类名不应当是动词。

变量

字母开头驼峰式命名,名字可以长但是得把功能,必要的参数描述清楚,函数名名应当是动词或动词短语,如postPayment、deletePage、save。并依Javabean标准加上get、set、is前缀。例如:xxx + deletePage + With/by + 需要的参数名 + And + 需要的参数名 + …..

全局变量:仅限在包内的全局变量,包外引用需要写接口,提供调用

局部变量:小写

变量命名基本上遵循相应的英文表达或简写,在相对简单的环境(对象数量少、针对性强)中,可以将一些名称由完整单词简写为单个字母,例如: user 可以简写为 u userID 可以简写 uid 若变量类型为 bool 类型,则名称应以 Has, Is, Can 或 Allow 开头:

1
2
3
4
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool

特有名词

如果变量为私有,且特有名词为首个单词,则使用小写,如 apiClient 其它情况都应当使用该名词原有的写法,如 APIClientrepoIDUserID 错误示例:UrlArray,应该写成urlArray或者URLArray

下面列举了一些常见的特有名词:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// A GonicMapper that contains a list of common initialisms taken from golang/lint
var LintGonicMapper = GonicMapper{
    "API":   true,
    "ASCII": true,
    "CPU":   true,
    "CSS":   true,
    "DNS":   true,
    "EOF":   true,
    "GUID":  true,
    "HTML":  true,
    "HTTP":  true,
    "HTTPS": true,
    "ID":    true,
    "IP":    true,
    "JSON":  true,
    "LHS":   true,
    "QPS":   true,
    "RAM":   true,
    "RHS":   true,
    "RPC":   true,
    "SLA":   true,
    "SMTP":  true,
    "SSH":   true,
    "TLS":   true,
    "TTL":   true,
    "UI":    true,
    "UID":   true,
    "UUID":  true,
    "URI":   true,
    "URL":   true,
    "UTF8":  true,
    "VM":    true,
    "XML":   true,
    "XSRF":  true,
    "XSS":   true,
}

常量

常量:大写,采用下划线

枚举
1
2
3
4
5
6
// 如果是枚举类型的常量,需要先创建相应类型:
type Scheme string
const (
    HTTP  Scheme = "http"
    HTTPS Scheme = "https"
)

如果模块的功能较为复杂、常量名称容易混淆的情况下,为了更好地区分枚举类型,可以使用完整的前缀:

1
2
3
4
5
6
7
type PullRequestStatus int

const (
    PULL_REQUEST_STATUS_CONFLICT PullRequestStatus = iota
    PULL_REQUEST_STATUS_CHECKING
    PULL_REQUEST_STATUS_MERGEABLE
)

单元测试

单元测试文件名命名规范为 example_test.go 测试用例的函数名称必须以 Test 开头,例如:TestExample

代码规范

导入包规范

如果包引入了三种类型的包,标准库包,程序内部包,第三方包,采用如下方式进行组织你的包:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import (
    "encoding/json"
    "strings"

    "myproject/models"
    "myproject/controller"
    "git.obc.im/obc/utils"

    "git.obc.im/dep/beego"
    "git.obc.im/dep/mysql"
)  

方法的接收器

名称 一般采用strcut的第一个字母且为小写,而不是this,me或者self

1
2
    type Student struct{} 
    func (s *Student)Get(){}

error 信息

error的信息不要采用大写字母,尽量保持你的错误简短,但是要足够表达你的错误的意思。\

注释规范

bug注释

针对代码中出现的bug,可以采用如下教程使用特殊的注释,在godocs可以做到注释高亮:

1
2
// BUG(astaxie):This divides by zero. 
var i float = 1/0

在编码阶段应该同步写好变量、函数、包的注释,最后可以利用godoc导出文档。注释必须是完整的句子,句子的结尾应该用句号作为结尾(英文句号)。注释推荐用英文,可以在写代码过程中锻炼英文的阅读和书写能力。而且用英文不会出现各种编码的问题。

包注释

每个包都应该有一个,一个位于package子句之前的块注释或行注释。包如果有多个go文件,只需要出现在一个go文件中即可。

1
2
// ping包实现了常用的ping相关的函数
package ping

函数注释

导出函数注释,第一条语句应该为一条概括语句,并且使用被声明的名字作为开头。

1
2
// 求a和b的和,返回sum。
func Myfunction(sum int) (a, b int) {