Go 文档注释与 Example

537 阅读3分钟

背景

在 Goland 中调用标准库的代码时,鼠标放在函数上会出现这个函数的相关文档。

cmd0 := exec.Command("go", "version")
stdout0, err := cmd0.StdoutPipe()
if err != nil {
    fmt.Println("[Error] 无法获取 cmd0的标准管道,err:", err)
    return
}

// 启动命令
if err = cmd0.Start(); err != nil {
    fmt.Println("[Error] cmd0 无法启动,err:", err)
    return
}

Goland中将鼠标悬停在StdoutPipe()方法上,可以看到以下内容

HXC)LN93}7GND%`R0O)%9LK.png

那么这个 Example 是哪来的?

示例测试

在一个包下新建文件,example.go

// Add 两数相加
//
// # 把两个整形相加
//
//   - a: 第一个参数
//   - b: 第二个参数
//
// See https://tip.golang.org/doc/comment for more information
//
// [Mul] 实现了乘法
func Add(a, b int) int {
    return a + b
}

// Mul 两个整数相乘
func Mul(a, b int) int {
    return a * b
}

// PrintUnorderedSlice 将传入的变长参数无序输出
func PrintUnorderedSlice(args ...string) []string {
    temp := make(map[string]struct{}, len(args))
    defer clear(temp)
    for _, arg := range args {
       temp[arg] = struct{}{}
    }

    stringSlice := make([]string, 0, len(args))
    for i := range temp {
       stringSlice = append(stringSlice, i)
    }
    return stringSlice
}

然后在同级目录下创建文件 example_test.go

func ExampleAdd() {
    c := Add(2, 3)
    d := Add(5, 6)
    fmt.Println(c)
    fmt.Println(d)
    // output:
    // 5
    // 11
}

func ExampleMul() {
    c := Mul(3, 4)
    fmt.Println(c)
    // output: 12
}

func ExamplePrintUnorderedSlice() {
    names := []string{"明前奶绿", "永雏塔菲", "嘉然", "米诺", "otto"}
    res := PrintUnorderedSlice(names...)
    for _, v := range res {
       fmt.Println(v)
    }
    // Unordered output:
    // 明前奶绿
    // 永雏塔菲
    // 嘉然
    // 米诺
    // otto
}

ExampleMul 演示的是单行输出示例,鼠标悬停在 Mul 函数上时显示如下:

image.png

ExampleAdd演示的是多行输出示例,显示内容如下:

image.png

ExamplePrintUnorderedSlice 演示的是无序输出示例,显示内容如下:

image.png

格式说明

  1. 示例测试函数名需要以"Example"开头;
  2. 检测单行输出格式为“// Output: <期望字符串>”;
  3. 检测多行输出格式为“// Output: \ <期望字符串> \ <期望字符串>”,每个期望字符串占一行;
  4. 检测无序输出格式为"// Unordered output: \ <期望字符串> \ <期望字符串>",每个期望字符串占一行;
  5. 测试字符串时会自动忽略字符串前后的空白字符;
  6. 如果测试函数中没有“Output”标识,则该测试函数不会被执行;
  7. 执行测试可以使用go test,此时该目录下的其他测试文件也会一并执行;

有接收器的函数的示例测试

// example.go

// UserBanned 用户被封禁状态
type UserBanned struct {
    Status   bool   // 状态
    Operator string // 操作者
}

// SwitchUserStatus 更换用户当前封禁-解封状态
func (ub *UserBanned) SwitchUserStatus() {
    ub.Status = !ub.Status
    ub.Operator = "me"
}
// example_test.go

func ExampleUserBanned_SwitchUserStatus() {
    ub := &UserBanned{}
    ub.SwitchUserStatus()
    fmt.Println(ub.Status)
    fmt.Println(ub.Operator)
    // output:
    // true
    // me
}

对于有接收器的函数,它的示例函数的函数名要命名为 'Example接收器名_函数名'

其他注释

  • Paragraphs 段落:段落是一段不缩进的非空行。
  • Headings 标题:标题是以数字符号(U+0023)开头的一行(# ),然后是空格和标题文本。要被识别为标题,该行必须不缩进,并通过空行与相邻段落文本隔开。
  • 文档链接: 文档链接是“[Name1]”或“[Name1.Name2]”格式的链接,用于引用当前包中导出的标识符,或“[pkg]”、“[pkg.Name1]”或“[pkg.Name1.Name2]”格式的链接,用于引用其他包中的标识符。
  • List列表:列表的语法有些类似于 markdown 的列表语法。

上文的 Add 函数的注释是一些简单的示例,更详细的用法参考官方博客 Go Doc Comments