在编码阶段同步写好类型、变量、函数、包注释,注释可以通过godoc
导出生成文档。
程序中每一个被导出的(大写的)名字,都应该有一个文档注释。
所有注释掉的代码在提交 Code Review 前都应该被删除,除非添加注释讲解为什么不删除, 并且标明后续处理建议(如删除计划)。
通用
- 不要用注释删除代码。
- 特殊实现需要注释。
风格
- 注释符
// /* */
与注释内容之间留一空格。 - 中英文之间应该留一空格。
- 注释结束添加结束标点符号,如句号、叹号等,参考标准库源码注释。
- 如果是英文注释,句子首字母应大写,参考标准库源码注释。
包注释
- 每个包都应该有一个包注释。
- 包如果有多个 go 文件,只需要出现在一个 go 文件中(一般是和包同名的文件)即可。
- 格式为
// Package 包名 包信息描述
。
// Package math provides basic constants and mathematical functions.
package math
// 或者
/*
Package template implements data-driven templates for generating textual
output such as HTML.
....
*/
package template
函数注释
- 导出的函数和方法(结构体或接口下的函数称为方法)都必须有注释。
注释描述函数或方法功能、调用方等信息。格式为 // 函数名 描述
。
注意,如果方法的接收器为不可导出类型,可以不注释,但需要质疑该方法可导出的必要性。
// NewtAttrModel 是属性数据层操作类的工厂方法
func NewAttrModel(ctx *common.Context) *AttrModel {
// TODO
}
- 避免参数语义不明确。
函数调用中意义不明确的实参可能会损害代码可读性。当参数名称的含义不明显时,请为参数添加 C 样式注释 (/* ... */
)
// Bad
// func printInfo(name string, isLocal, done bool)
printInfo("foo", true, true)
// Good
// func printInfo(name string, isLocal, done bool)
printInfo("foo", true /* isLocal */, true /* done */)
对于上面的示例代码,还有一种更好的处理方式是将上面的 bool 类型换成自定义类型。将来,该参数可以支持不仅仅局限于两个状态(true/false)。
type Region int
const (
UnknownRegion Region = iota
Local
)
type Status int
const (
StatusReady Status= iota + 1
StatusDone
// Maybe we will have a StatusInProgress in the future.
)
func printInfo(name string, region Region, status Status)
- 非导出的函数,如果比较简单,不需要注释。
- 解析函数应该注明解析字符串的范例,并明确不能处理的异常情况。
结构体注释
- 每个需要导出的自定义结构体或者接口都必须有注释说明。
注释对结构进行简要介绍,放在结构体定义的前一行。格式为 // 结构体名 描述
。
- 必要情况下字段给出注释。
结构体内的可导出成员变量名,如果是个生僻词或意义不明确的词,必须要单独给出注释,放在成员变量的前一行或同一行的末尾。
// User 用户结构定义了用户基础信息。
type User struct {
Name string
Email string
Demographic string // 族群
}
变量和常量注释
- 每个需要导出的变量和常量都必须有注释说明。
注释对变量和常量进行简要介绍,放在常量或变量定义的前一行。独行注释格式为:"// 变量名 描述",斜线后面紧跟一个空格。
// FlagConfigFile 配置文件的命令行参数名。
const FlagConfigFile = "--config"
// FullName 返回指定用户名的完整名称。
var FullName = func(username string) string {
return fmt.Sprintf("fake-%s", username)
}
- 大块变量或常量定义时的注释方式。
块注释即在代码块前给出一个总的说明,然后每行变量或常量的末尾给出详细注释,这样看起来更加简洁。
// 命令行参数。
const (
FlagConfigFile1 = "--config" // 配置文件的命令行参数名 1。
FlagConfigFile2 = "--config" // 配置文件的命令行参数名 2。
FlagConfigFile3 = "--config" // 配置文件的命令行参数名 3。
FlagConfigFile4 = "--config" // 配置文件的命令行参数名 4。
)
- 命名清晰的地方,不要添加无意义的注释。
类型注释
- 每个需要导出的类型定义(type definition)和类型别名(type aliases)都必须有注释说明。
- 该注释对类型进行简要介绍,放在定义的前一行。
- 格式为:"// 类型名 描述"。
// StorageClass 存储类型
type StorageClass string
// FakeTime 标准库时间的类型别名
type FakeTime = time.Time
接口注释
- 导出与非导出接口均需要有注释。
- 需要描述谁,在什么场景下,如何使用接口。