原文: https://blog.golang.org/examplesgit
Go自動生成的文檔中有時你會看到代碼例子,這些例子還能夠經過點擊網站上的Run按鈕運行。而這些例子是從測試代碼中提取出來的。github
這些代碼例子是具備可測性的,而帶來的優勢就是當API變化的時候,代碼可以及時的同步。標準庫中有不少庫都包含代碼例子,好比strings packagegolang
這篇文章將會教會你如何給一個庫寫例子代碼。網絡
例子代碼都是寫在庫的測試用例集裏面的(以_test.go
結尾的文件)。跟普通的測試函數不一樣的是,例子代碼的函數不接受任何參數,命令函數命名以Example
開頭(普通測試函數是以Test
開頭的)框架
Go的官方例子代碼庫裏能夠找到一個 stringutil庫,這個庫實現了Reverse
函數ide
package stringutil_test import ( "fmt" "github.com/golang/example/stringutil" ) func ExampleReverse() { fmt.Println(stringutil.Reverse("hello")) // Output: olleh }
上面這段代碼應該能夠在example_test.go
裏面找到。這段例子代碼會自動在godoc中的Reverse函數的說明下找到。函數
運行該庫的測試用例,咱們能夠看到相關的Example函數也跟着一塊兒運行了。測試
$ go test -v === RUN TestReverse --- PASS: TestReverse (0.00s) === RUN: ExampleReverse --- PASS: ExampleReverse (0.00s) PASS ok github.com/golang/example/stringutil 0.009s
程序是如何肯定Example函數是否PASS呢?網站
當運行Example的測試用例的時候,測試框架捕獲了其標準輸出,而且用其跟註釋中`Output: 開頭的內容進行的對比,來肯定是否調用成功ui
簡單的修改下注釋,就可讓這個測試用例FAIL了
func ExampleReverse() { fmt.Println(stringutil.Reverse("hello")) // Output: golly }
從新運行後的效果
$ go test --- FAIL: ExampleReverse (0.00s) got: olleh want: golly FAIL
若是咱們把Example裏面的註釋都刪掉呢
func ExampleReverse() { fmt.Println(stringutil.Reverse("hello")) }
全部Example開頭的函數雖然會寫到文檔中,可是不會做爲測試程序執行了
$ go test -v === RUN TestReverse --- PASS: TestReverse (0.00s) PASS ok github.com/golang/example/stringutil 0.009s
這種狀況適用於依賴外部環境,沒法做爲單側用例執行的,好比依賴一個外部的網絡服務。
Godoc是經過名字來將其關聯到相應的函數的
func ExampleFoo() // 做爲Foo函數或者類型例子 func ExampleBar_Qux() // 做爲Bar類型的Qux函數例子 func Example() // 做爲整個庫的例子
經過這種規則,godoc將ExampleReverse
函數對應到了Reverse
這個函數
經過增長 下劃線+小寫字母開頭的單詞做爲後綴,一個函數能夠對應多個例子。例如
func ExampleReverse() func ExampleReverse_second() func ExampleReverse_third()
這3個函數對對應於Reverse
這個函數。
有些時候一個函數的例子已經沒法說明一個函數該如何使用。
TODO 待翻譯(困死了,先睡會)
For instance, to demonstrate the sort package we should show an implementation of sort.Interface. Since methods cannot be declared inside a function body, the example must include some context in addition to the example function.
To achieve this we can use a "whole file example." A whole file example is a file that ends in _test.go and contains exactly one example function, no test or benchmark functions, and at least one other package-level declaration. When displaying such examples godoc will show the entire file.
Here is a whole file example from the sort package:
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 implements sort.Interface for []Person based on // the Age field. 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] }
A package can contain multiple whole file examples; one example per file. Take a look at the sort package's source code to see this in practice.
Godoc examples are a great way to write and maintain code as documentation. They also present editable, working, runnable examples your users can build on. Use them!
By Andrew Gerrand