Effective Go: 注释

207 阅读2分钟

这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

Go 提供 C 风格的 /* */ 块注释和 C++ 风格的 // 行注释。行注释是规范使用;块注释主要作为包注释出现,但在表达式中或禁用大量代码时很有用。

godoc 处理 Go 源文件可以提取有关包内容的文档。在最上层声明的注释,没有换行符,与声明一起被提取出来作为项目的解释性文本。这些评论的性质和风格决定了 godoc 生成的文档的质量。

每个包都应该有一个包注释,在包之前写上块注释。对于多文件包,包注释只需要出现在一个文件中,任何一个都可以。包注释应介绍包并提供与整个包相关的信息。它将首先出现在 godoc 页面上,并应设置后面的详细文档。下面是个案例:

/*
Package regexp implements a simple library for regular expressions.

The syntax of the regular expressions accepted is:

    regexp:
        concatenation { '|' concatenation }
    concatenation:
        { closure }
    closure:
        term [ '*' | '+' | '?' ]
    term:
        '^'
        '$'
        '.'
        character
        '[' [ '^' ] character-ranges ']'
        '(' regexp ')'
*/
package regexp

如果包功能很简单,那么包的注释可以很简洁

// Package path implements utility routines for
// manipulating slash-separated filename paths.

注释不需要额外的格式,例如各种星星横幅。生成的输出甚至可能不会以固定宽度的字体呈现,因此不要依赖间距进行对齐,gofmt会帮我们处理这个问题。注释是未解释的纯文本,因此 HTML 格式的注释和其他注释(例如 *this* )将逐字复制,不应使用。 godoc 所做的一项调整是以固定宽度的字体显示缩进文本,适用于程序片段。 fmt 包的包注释遵循了已上原则是个很好的例子。

根据上下文,godoc 甚至可能不会重新格式化注释,因此请确保它们直接看起来不错:使用正确的拼写、标点符号和句子结构,折叠长行等。

在包内,紧接在顶级声明之前的任何注释都用作该声明的文档注释。程序中的每个导出(大写)名称都应该有一个文档注释

文档注释作为完整的句子效果最好,它允许各种自动演示。第一句话应该是一个句子摘要,以被声明的名字开头,如下:

// Compile parses a regular expression and returns, if successful,
// a Regexp that can be used to match against text.
func Compile(str string) (*Regexp, error) {

如果每个 doc 注释都以其描述的项目名称开头,则可以使用 go 工具的 doc 子命令并通过 grep 运行输出。 想象一下,你如果不记得上述那个方法名字“Compile”,但正在寻找这个正则表达式的解析函数,那你可以运行下面这个命令来找到它

$ go doc -all regexp | grep -i parse

如果包中的所有文档注释都以“This function...”开头,grep 将无法帮助您记住名称。 但是因为包以名称开始每个文档注释,所以您会看到类似这样的内容,它会回忆起您正在寻找的单词。

$ go doc -all regexp | grep -i parse
    Compile parses a regular expression and returns, if successful, a Regexp
    MustCompile is like Compile but panics if the expression cannot be parsed.
    parsed. It simplifies safe initialization of global variables holding
$

Go 的声明语法允许对声明进行分组。 单个文档注释可以引入一组相关的常量或变量。 由于提供了整个声明,这样的评论通常比较敷衍的。

// Error codes returned by failures to parse an expression.
var (
    ErrInternal      = errors.New("regexp: internal error")
    ErrUnmatchedLpar = errors.New("regexp: unmatched '('")
    ErrUnmatchedRpar = errors.New("regexp: unmatched ')'")
    ...
)

分组同样可以体现项目之间存在某种关系,例如下面这个例子

var (
    countLock   sync.Mutex
    inputCount  uint32
    outputCount uint32
    errorCount  uint32
)