- It is recommended that a line of code does not exceed 120 characters. If the part exceeds, please use an appropriate line break method. But there are also some exception scenarios, such as import lines, code automatically generated by tools, and struct fields with tags.
- All code must be formatted with `goimports` (it is recommended to set the code Go code editor to: run `goimports` on save).
- 文件长度不能超过800行。
- Do not use relative paths to import packages, such as `import ../util/net`.
- 函数长度不能超过80行。
- Import aliases must be used when the package name does not match the last directory name of the import path, or when multiple identical package names conflict.
When multiple variables need to be used in a function, the `var` declaration can be used at the beginning of the function. Declaration outside the function must use `var`, do not use `:=`, it is easy to step on the scope of the variable.
```go
```go
var (
var (
@ -60,7 +56,7 @@ var (
)
)
```
```
- 在初始化结构引用时,请使用`&T{}`代替`new(T)`,以使其与结构体初始化一致。
- When initializing a structure reference, please use `&T{}` instead of `new(T)` to make it consistent with structure initialization.
```go
```go
// bad
// bad
@ -71,7 +67,7 @@ sptr.Name = "bar"
sptr := &T{Name: "bar"}
sptr := &T{Name: "bar"}
```
```
- struct 声明和初始化格式采用多行,定义如下。
- The struct declaration and initialization format takes multiple lines and is defined as follows.
```go
```go
type User struct{
type User struct{
@ -85,7 +81,7 @@ user := User{
}
}
```
```
- 相似的声明放在一组,同样适用于常量、变量和类型声明。
- Similar declarations are grouped together, and the same applies to constant, variable, and type declarations.
```go
```go
// bad
// bad
@ -99,14 +95,14 @@ import (
)
)
```
```
- 尽可能指定容器容量,以便为容器预先分配内存,例如:
- Specify container capacity where possible to pre-allocate memory for the container, for example:
```go
```go
v := make(map[int]string, 4)
v := make(map[int]string, 4)
v := make([]string, 0, 4)
v := make([]string, 0, 4)
```
```
- 在顶层,使用标准var关键字。请勿指定类型,除非它与表达式的类型不同。
- At the top level, use the standard var keyword. Do not specify a type unless it is different from the type of the expression.
- Embedded types (such as mutexes) should be at the top of the field list within the struct, and there must be a blank line separating embedded fields from regular fields.
- `error` is returned as the value of the function, `error` must be handled, or the return value assigned to explicitly ignore. For `defer xx.Close()`, there is no need to explicitly handle it.
```go
```go
func load() error {
func load() error {
@ -171,7 +167,7 @@ load()
_ = load()
_ = load()
```
```
- `error`作为函数的值返回且有多个返回值的时候,`error`必须是最后一个参数。
- When `error` is returned as the value of a function and there are multiple return values, `error` must be the last parameter.
```go
```go
// bad
// bad
@ -185,7 +181,7 @@ func load() (int, error) {
}
}
```
```
- 尽早进行错误处理,并尽早返回,减少嵌套。
- Perform error handling as early as possible and return as early as possible to reduce nesting.
```go
```go
// bad
// bad
@ -203,7 +199,7 @@ if err != nil {
// normal code
// normal code
```
```
- 如果需要在 if 之外使用函数调用的结果,则应采用下面的方式。
- If you need to use the result of the function call outside if, you should use the following method.
```go
```go
// bad
// bad
@ -218,7 +214,7 @@ if err != nil {
}
}
```
```
- 错误要单独判断,不与其他逻辑组合判断。
- Errors should be judged independently, not combined with other logic.
```go
```go
// bad
// bad
@ -241,7 +237,7 @@ if v == nil {
}
}
```
```
- 如果返回值需要初始化,则采用下面的方式。
- If the return value needs to be initialized, use the following method.
```go
```go
v, err := f()
v, err := f()
@ -251,8 +247,8 @@ if err != nil {
}
}
```
```
- 错误描述建议
- Bug description suggestions
- 错误描述用小写字母开头,结尾不要加标点符号,例如:
- Error descriptions start with a lowercase letter and do not end with punctuation, for example:
```go
```go
// bad
// bad
errors.New("Redis connection failed")
errors.New("Redis connection failed")
@ -261,34 +257,34 @@ if err != nil {
// good
// good
errors.New("redis connection failed")
errors.New("redis connection failed")
```
```
- 告诉用户他们可以做什么,而不是告诉他们不能做什么。
- Tell users what they can do, not what they can't.
- 当声明一个需求时,用must 而不是should。例如,`must be greater than 0、must match regex '[a-z]+'`。
- When declaring a requirement, use must instead of should. For example, `must be greater than 0, must match regex '[a-z]+'`.
- 当声明一个格式不对时,用must not。例如,`must not contain`。
- When declaring that a format is incorrect, use must not. For example, `must not contain`.
- 当声明一个动作时用may not。例如,`may not be specified when otherField is empty、only name may be specified`。
- Use may not when declaring an action. For example, `may not be specified when otherField is empty, only name may be specified`.
- 引用文字字符串值时,请在单引号中指示文字。例如,`ust not contain '..'`。
- When quoting a literal string value, indicate the literal in single quotes. For example, `ust not contain '..'`.
- 当引用另一个字段名称时,请在反引号中指定该名称。例如,must be greater than `request`。
- When referencing another field name, specify that name in backticks. For example, must be greater than `request`.
- 指定不等时,请使用单词而不是符号。例如,`must be less than 256、must be greater than or equal to 0 (不要用 larger than、bigger than、more than、higher than)`。
- When specifying unequal, use words instead of symbols. For example, `must be less than 256, must be greater than or equal to 0 (do not use larger than, bigger than, more than, higher than)`.
- 指定数字范围时,请尽可能使用包含范围。
- When specifying ranges of numbers, use inclusive ranges whenever possible.
- 建议 Go 1.13 以上,error 生成方式为 `fmt.Errorf("module xxx: %w", err)`。
- Go 1.13 or above is recommended, and the error generation method is `fmt.Errorf("module xxx: %w", err)`.
### 1.4 panic处理
### 1.4 panic processing
- 在业务逻辑处理中禁止使用panic。
- Panic is prohibited in business logic processing.
- In the main package, panic is only used when the program is completely inoperable, for example, the file cannot be opened, the database cannot be connected, and the program cannot run normally.
- In the main package, use `log.Fatal` to record errors, so that the program can be terminated by the log, or the exception thrown by the panic can be recorded in the log file, which is convenient for troubleshooting.
- 可导出的接口一定不能有panic。
- An exportable interface must not panic.
- 包内建议采用error而不是panic来传递错误。
- It is recommended to use error instead of panic to convey errors in the package.
### 1.5 单元测试
### 1.5 Unit Tests
- 单元测试文件名命名规范为 `example_test.go`。
- The unit test filename naming convention is `example_test.go`.
- 每个重要的可导出函数都要编写测试用例。
- Write a test case for every important exportable function.
- 因为单元测试文件内的函数都是不对外的,所以可导出的结构体、函数等可以不带注释。
- Because the functions in the unit test file are not external, the exportable structures, functions, etc. can be uncommented.
The naming convention is a very important part of the code specification. A uniform, short, and precise naming convention can greatly improve the readability of the code and avoid unnecessary bugs.
### 2.1 包命名
### 2.1 Package Naming
- 包名必须和目录名一致,尽量采取有意义、简短的包名,不要和标准库冲突。
- The package name must be consistent with the directory name, try to use a meaningful and short package name, and do not conflict with the standard library.
- 包名全部小写,没有大写或下划线,使用多级目录来划分层级。
- Package names are all lowercase, without uppercase or underscores, and use multi-level directories to divide the hierarchy.
- 项目名可以通过中划线来连接多个单词。
- Item names can connect multiple words with dashes.
- 包名以及包所在的目录名,不要使用复数,例如,是`net/url`,而不是`net/urls`。
- Do not use plurals for the package name and the directory name where the package is located, for example, `net/url` instead of `net/urls`.
- 不要用 common、util、shared 或者 lib 这类宽泛的、无意义的包名。
- Don't use broad, meaningless package names like common, util, shared or lib.
- 包名要简单明了,例如 net、time、log。
- The package name should be simple and clear, such as net, time, log.
- The function name is in camel case, and the first letter is uppercase or lowercase according to the access control decision,For example: `MixedCaps` or `mixedCaps`.
- Code automatically generated by code generation tools (such as `xxxx.pb.go`) and underscores used to group related test cases (such as `TestMyFunction_WhatIsBeingTested`) exclude this rule.
### 2.3 文件命名
### 2.3 File Naming
- 文件名要简短有意义。
- Keep the filename short and meaningful.
- 文件名应小写,并使用下划线分割单词。
- Filenames should be lowercase and use underscores to separate words.
- Same as the code specification, single-line comments should not be too long, and no more than 120 characters are allowed. If it exceeds, please use a new line to display, and try to keep the format elegant.
- A comment must be a complete sentence, starting with the content to be commented and ending with a period, `the format is // name description.`. For example:
- All commented out code should be deleted before submitting code review, otherwise, it should explain why it is not deleted, and give follow-up processing suggestions.
- 在多段注释之间可以使用空行分隔加以区分,如下所示:
- Multiple comments can be separated by blank lines, as follows:
```go
```go
// Package superman implements methods for saving the world.
// Package superman implements methods for saving the world.
- When there is a large block of constant or variable definition, you can comment a general description in front, and then comment the definition of the constant in detail before or at the end of each line of constant, for example:
```go
```go
// Code must start with 1xxxxx.
// Code must start with 1xxxxx.
const (
const (
@ -535,10 +531,10 @@ const (
ErrValidation
ErrValidation
)
)
```
```
### 3.3 结构体注释
### 3.3 Structure Annotation
- 每个需要导出的结构体或者接口都必须有注释说明,格式为 `// 结构体名 结构体描述.`。
- Each structure or interface that needs to be exported must have a comment description, the format is `// structure name structure description.`.
- The name of the exportable member variable in the structure, if the meaning is not clear, a comment must be given and placed before the member variable or at the end of the same line. For example:
```go
```go
// User represents a user restful resource. It is also used as gorm model.
// User represents a user restful resource. It is also used as gorm model.
@ -554,9 +550,9 @@ type User struct {
}
}
```
```
### 3.4 方法注释
### 3.4 Method Notes
每个需要导出的函数或者方法都必须有注释,格式为// 函数名 函数描述.,例如:
Each function or method that needs to be exported must have a comment, the format is // function name function description., for examplelike:
```go
```go
// BeforeUpdate run before update database record.
// BeforeUpdate run before update database record.
- Each type definition and type alias that needs to be exported must have a comment description, the format is `// type name type description.`, for example:
```go
```go
// Code defines an error code type.
// Code defines an error code type.
type Code int
type Code int
```
```
## 4. 类型
## 4. Type
### 4.1 字符串
### 4.1 Strings
- 空字符串判断。
- Empty string judgment.
```go
```go
// bad
// bad
@ -593,7 +589,7 @@ if len(s) == 0 {
}
}
```
```
- `[]byte`/`string`相等比较。
- `[]byte`/`string` equality comparison.
```go
```go
// bad
// bad
@ -611,7 +607,7 @@ bytes.Compare(s1, s2) == 0
bytes. Compare(s1, s2) != 0
bytes. Compare(s1, s2) != 0
```
```
- 复杂字符串使用raw字符串避免字符转义。
- Complex strings use raw strings to avoid character escaping.
- If the function returns two or three arguments of the same type, or if the meaning of the result is not clear from the context, use named returns, otherwise it is not recommended to use named returns, for example:
```go
```go
func coordinate() (x, y float64, err error) {
func coordinate() (x, y float64, err error) {
// normal code
// normal code
}
}
```
```
- 传入变量和返回变量都以小写字母开头。
- Both incoming and returned variables start with a lowercase letter.
- 尽量用值传递,非指针传递。
- Try to pass by value instead of pointer.
- 参数数量均不能超过5个。
- The number of parameters cannot exceed 5.
- 多返回值最多返回三个,超过三个请使用 struct。
- Multiple return values can return up to three, and if there are more than three, please use struct.
- When resources are created, resources should be released immediately after defer (defer can be used boldly, the performance of defer is greatly improved in Go1.14 version, and the performance loss of defer can be ignored even in performance-sensitive businesses).
- 先判断是否错误,再defer释放资源,例如:
- First judge whether there is an error, and then defer to release resources, for example:
```go
```go
rep, err := http. Get(url)
rep, err := http. Get(url)
@ -835,46 +831,46 @@ if err != nil {
defer resp.Body.Close()
defer resp.Body.Close()
```
```
### 6.3 方法的接收器
### 6.3 Method Receiver
- 推荐以类名第一个英文首字母的小写作为接收器的命名。
- It is recommended to use the lowercase of the first English letter of the class name as the name of the receiver.
- 接收器的命名在函数超过20行的时候不要用单字符。
- Don't use a single character in the name of the receiver when the function exceeds 20 lines.
- 接收器的命名不能采用me、this、self这类易混淆名称。
- The name of the receiver cannot use confusing names such as me, this, and self.
### 6.4 嵌套
### 6.4 Nesting
- 嵌套深度不能超过4层。
- The nesting depth cannot exceed 4 levels.
### 6.5 变量命名
### 6.5 Variable Naming
- 变量声明尽量放在变量第一次使用的前面,遵循就近原则。
- The variable declaration should be placed before the first use of the variable as far as possible, following the principle of proximity.
- 如果魔法数字出现超过两次,则禁止使用,改用一个常量代替,例如:
- If the magic number appears more than twice, it is forbidden to use it and use a constant instead, for example:
```go
```go
// PI...
// PI...
const Prise = 3.14
const Price = 3.14
func getAppleCost(n float64) float64 {
func getAppleCost(n float64) float64 {
return Prise * n
return Price * n
}
}
func getOrangeCost(n float64) float64 {
func getOrangeCost(n float64) float64 {
return Prise * n
return Price * n
}
}
```
```
## 7. GOPATH 设置规范
## 7. GOPATH setting specification
- Go 1.11 之后,弱化了 GOPATH 规则,已有代码(很多库肯定是在1.11之前建立的)肯定符合这个规则,建议保留 GOPATH 规则,便于维护代码。
- After Go 1.11, the GOPATH rule has been weakened. Existing code (many libraries must have been created before 1.11) must conform to this rule. It is recommended to keep the GOPATH rule to facilitate code maintenance.
- 建议只使用一个 GOPATH,不建议使用多个 GOPATH。如果使用多个GOPATH,编译生效的 bin 目录是在第一个 GOPATH 下。
- Only one GOPATH is recommended, multiple GOPATHs are not recommended. If multiple GOPATHs are used, the bin directory where compilation takes effect is under the first GOPATH.
## 8. 依赖管理
## 8. Dependency Management
- Go 1.11 以上必须使用 Go Modules。
- Go 1.11 and above must use Go Modules.
- 使用Go Modules作为依赖管理的项目时,不建议提交vendor目录。
- When using Go Modules as a dependency management project, it is not recommended to submit the vendor directory.
- 使用Go Modules作为依赖管理的项目时,必须提交go.sum文件。
- When using Go Modules as a dependency management project, the go.sum file must be submitted.
- Minimize the use of global variables, but pass parameters, so that each function is "stateless". This reduces coupling and facilitates division of labor and unit testing.
- 在编译时验证接口的符合性,例如:
- Verify interface compliance at compile time, for example:
- When the server processes a request, it should create a context, save the relevant information of the request (such as requestID), and pass it in the function call chain.
- string represents an immutable string variable, modifying string is a relatively heavy operation, and basically needs to re-apply for memory. Therefore, if there is no special need, use []byte more when you need to modify.