在 Godoc 文档网页里直接执行 Go 代码
Andrew Gerrand
2015 年 5 月 7 日
介绍
Godoc 示例 是 Go 代码的片段, 这些片段显示为软件包文档, 并通过将其作为测试运行进行验证. 用户也可以通过访问该软件包的 godoc 网页并单击相关的 "运行" 按钮来运行它们.
拥有可执行文件的软件包可确保该信息不会随着 API 的更改而过时.
标准库包含许多此类示例 (例如, 可参阅 strings
程序包).
本文介绍了如何编写您自己的示例函数.
示例也是测试
示例是作为包的测试套件的一部分进行编译 (可选) 的.
与典型测试一样, 示例是驻留在软件包的 _test.go
文件中的函数. 与普通测试函数不同的是, 示例函数不带任何参数, 而是以 Example
开头, 而不是 Test
.
stringutil
程序包是Go示例库. 这是一个演示其 Reverse
函数的示例:
package stringutil_test
import (
"fmt"
"github.com/golang/example/stringutil"
)
func ExampleReverse() {
fmt.Println(stringutil.Reverse("hello"))
// Output: olleh
}
该代码可能位于 stringutil
目录中的 example_test.go
中.
Godoc 将在 Reverse
函数的文档中提供此示例:
运行该软件包的测试套件, 我们可以看到示例函数的执行没有经过我们的进一步安排:
$ go test -v
=== RUN TestReverse
--- PASS: TestReverse (0.00s)
=== RUN: ExampleReverse
--- PASS: ExampleReverse (0.00s)
PASS
ok github.com/golang/example/stringutil 0.009s
Output 注释
ExampleReverse
函数 "passes" 是什么意思?
在执行示例时, 测试框架将捕获写入标准输出的数据, 然后将输出与示例的 "Output:" 注释进行比较. 如果测试的输出与其输出注释匹配, 则测试通过.
要查看失败的示例, 我们可以将输出注释文本更改为明显不正确的内容
func ExampleReverse() {
fmt.Println(stringutil.Reverse("hello"))
// Output: golly
}
并再次运行测试:
$ go test
--- FAIL: ExampleReverse (0.00s)
got:
olleh
want:
golly
FAIL
如果我们完全删除输出注释
func ExampleReverse() {
fmt.Println(stringutil.Reverse("hello"))
}
然后示例函数被编译但未执行:
$ go test -v
=== RUN TestReverse
--- PASS: TestReverse (0.00s)
PASS
ok github.com/golang/example/stringutil 0.009s
没有 output 注释的示例可用于演示无法作为单元测试运行的代码, 例如访问网络的代码, 同时保证示例至少可以编译.
示例的函数名称
Godoc 使用命名约定将示例函数与包级标识符关联.
func ExampleFoo() // 记录 Foo 函数或类型
func ExampleBar_Qux() // 记录 Bar 类型的 Qux 方法
func Example() // 记录整个包
按照此约定, godoc 将显示 ExampleReverse
示例以及 Reverse
函数的文档.
对于给定的标识符, 使用以下划线开头, 小写字母的后缀来提供多个示例. 这些示例记录了 Reverse
函数:
func ExampleReverse()
func ExampleReverse_second()
func ExampleReverse_third()
更大的示例
有时我们不仅只需要一个函数来编写一个很好的例子.
例如, 为了演示 sort
程序包, 我们应该显示 sort.Interface
的实现. 由于不能在函数体内声明方法, 因此该示例除了示例函数外还必须包括一些上下文.
为此, 我们可以使用 "整个文件示例". 整个文件示例是一个以 _test.go
结尾的文件, 并且仅包含一个示例函数, 没有测试或基准测试函数以及至少一个其他程序包级声明. 显示此类示例时, godoc 将显示整个文件.
这是 sort
程序包中的整个文件示例:
package sort_test
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s: %d", p.Name, p.Age)
}
// ByAge 基于年龄字段为 []Person 实现 sort.Interface.
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func Example() {
people := []Person{
{"Bob", 31},
{"John", 42},
{"Michael", 17},
{"Jenny", 26},
}
fmt.Println(people)
sort.Sort(ByAge(people))
fmt.Println(people)
// Output:
// [Bob: 31 John: 42 Michael: 17 Jenny: 26]
// [Michael: 17 Jenny: 26 Bob: 31 John: 42]
}
一个包可以包含多个完整的文件示例. 每个文件一个示例. 可以在 sort
程序包的源代码 实践中看到.
总结一下
Godoc 示例是编写和维护代码文档的好方法. 它们还提供了用户可以建立的可编辑, 可运行且可运行的示例. 盘她!
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: