如何寫高大上的 godoc(Go 文檔)

做 Go 開發時,我們在開源項目的主頁上我們經常可以看到這樣的一個徽章:

點擊徽章,就可以打開 godoc.org 的網頁,網頁中給出了這個開源項目所對應的 Go 文檔。作爲 Go 語言的新手,我一度以爲,godoc.org 上面的文檔是需要開發者上傳並審覈的——要不然那些文檔咋都顯得那麼專業呢。

然而當我寫自己的輪子時,慢慢的我就發現並非如此。劃重點:在 godoc.org 上的文檔,都是 Go 自動從開源項目的工程代碼中搜集、格式化後展現出來的。換句話說,每個人都可以寫自己的 godoc 並且展示在 godoc.org 上,只需要遵從 godoc 的格式標準即可,也不需要任何審覈動作。

本文章的目的是通過例子,簡要說明 godoc 的格式,讓讀者也可以自己寫一段高大上的 godoc。以下內容以我自己的 jsonvalue 倉庫爲例子。其對應的 godoc 在這裏。讀者可以點開,並與代碼中的內容做參考對比。

本文地址:https://segmentfault.com/a/1190000020944376,首發於雲+社區

什麼是 godoc

顧名思義,godoc 就是 Go 語言的文檔。在實際應用中,godoc 可能可以指以下含義:

  1. https://godoc.org 中的內容
  2. Go 開發工具安裝之後,自帶的一個命令,就叫做 godoc
  3. Go 工具包的文檔以及生成該文檔所相關的格式

我們從 Go 自帶的 godoc 工具講起吧。前面我們說到的 godoc.org,是 Go 最爲官方的文檔網站。其中我們可以查閱 Go 原生 package 的文檔說明。而 godoc 命令的作用,則是可以讓我們在本地建立一個屬於自己的 godoc 網站服務(官方的 godoc 其實也基本上是用同一個工具建立起來的)。

自建的 godoc 有兩個作用,一是解決某局域網內無法訪問 godoc.org 的尷尬,另一個則是可以本地調試自己的文檔。

我們可以用下面的命令在本地啓動自己的 godoc 服務:

godoc -http=127.0.0.1:6060 -play

或者簡寫爲:

godoc -http=:6060 -play

在瀏覽器輸入 http://127.0.0.1:6060 之後,就可以看到熟悉的 Go 文檔頁面了:

原理上,godoc 讀取的包路徑來自於 $GOROOT。因此,如果你要讓本地的 godoc 認識並解析你自己的開發包,就應該在 $GOROOT 目錄下按照路徑結構放好自己的工程代碼——軟鏈接也是支持的。比如筆者的 jsonvalue 包,我放在了這個路徑下:~/project/github.com/Andrew-M-C/go.jsonvalue,於是我就在 $GOROOT 下建了軟鏈接:

$ go env | grep GOROOT | sed 's/GOROOT=//g' | xargs cd
$ ln -s ~/project/github.com ./

然後在瀏覽器中輸入 http://127.0.0.1:6060/pkg/github.com/Andrew-M-C/go.jsonvalue/,就可以看到和 godoc.org 一樣的頁面了。

godoc 一覽

Go 秉承 “註釋即文檔” 的理念,符合 godoc 的文檔均從 Go 代碼中提取並生成。我們還是從 jsonvalue 的 godoc 來看,一個一個說明。在 godoc 中,文檔包含三大部分:

 組成  作用
Overview 總覽 包含包的 import 語句和概要說明
Index 目錄 包含包中可見性爲 public 的常量、類型、方法、函數的總目錄及說明
Examples 示例 包含文檔中所有示例的快速跳轉
Files 文件 列出了包中所有代碼文件的超鏈接

其中第四部分無關緊要。下面我們按順序說明前三部分

godoc 的 Overview

Package jsonvalue 的 Overview 部分包含了三部分內容:

  • import 語句
  • 文字說明
  • 代碼部分

其中 import 部分是 godoc 自動按照 URL 生成的,這個不用管。至於文字部分和代碼部分,godoc 都是從源碼中提取出來的。提取的原則是:

  • 在代碼中所有 package jsonvalue 語句中,找到其上方緊跟着的 // jsonvalue XXX 或者是 /* jsonvalue XXX */ 註釋塊
  • 註釋塊可以有多行,但必須是連續的 // 或者 /* XXX */ 開頭。如果需要換行,則留一行空註釋
  • 如果找到多個符合條件的註釋,則按照文件字母序顯示——建議把 Overview 放在一個註釋塊中,而不要分散撰寫。

比如 jsonvalue 的 Overview 說明,統一放在 doc.go 中,這個文件中只有 package jsonvalue 語句以及包說明——這也是不少文章中推薦的做法。

Overview 的文字部分

請讀者打開 doc.go,然後對比 godoc,就可以對照着看到文字部分是怎麼被 godoc 呈現出來的。

Overview 的代碼部分

在註釋中,如果在 // 後面的註釋文本中,如果以 tab 進行了鎖進,那麼 godoc 會將這一行視爲代碼塊。比如下面這一段:

其中 "As a quick start:" 行的左邊分別爲:兩個斜槓 + 一個空格。這一行,godoc 視爲普通文字;而其餘部分的左邊爲:兩個斜槓 + 一個空格 + 一個tab,被 godoc 視爲代碼部分。於是我們在 godoc 網頁上,就可以看到這樣的顯示結果了:

godoc 的代碼文檔

godoc 工具會搜尋代碼中所有源碼文件(自測文件除外),然後展示到頁面上。搜索的依據如下:

  • 搜尋對象是代碼中所有的公共部分,包括常量、變量、接口、類型、函數
  • 與 Overview 類似,緊跟着一個公共元素的、以該元素開頭的註釋段,會被 godoc 視爲該元素的註釋
  • 換行邏輯和代碼塊邏輯的處理也與 Overview 相同

不過在源碼說明中,更多的採用代碼示例來說明邏輯,因此在這一環節中,代碼塊比較少用。

這裏我用 jsonvalueAt() 函數爲例。在代碼中,對於 Set() 函數我是這麼寫的(請無視我蹩腳的英文):

// At completes the following operation of Set(). It defines posttion of value in Set() and return the new value set.
//
// The usage of At() is perhaps the most important. This function will recursivly search for child value, and set the new value specified by Set() or SetXxx() series functions. Please unfold and read the following examples, they are important.
func (s *Set) At(firstParam interface{}, otherParams ...interface{}) (*V, error) {
    ......
}

godoc 解析並格式化效果如下:

godoc 的代碼示例

讀者可以注意到,在我的 At() 函數下,除了上文提到的文檔正文之外,還有五個代碼示例。那麼,文檔中的代碼示例又應該如何寫呢?

首先,我們應該新建至少一個文件,專門用來存放示例代碼。比如我就把示例代碼寫在了 example_jsonvalue_test.go 文件中。這個文件的 package 名也不得與當前包名相同,而應該命名爲 包名_test 的格式。

示例代碼的聲明

如何聲明一個示例代碼,這裏我舉兩個例子。首先是在 At() 函數下名爲 “Example (1)” 的示例。在代碼中,我把這個函數命名爲:

func ExampleSet_At_1() {
    ......
}

這個函數命名有幾個部分:

 函數名組成部分   說明
Example 這是示例代碼的固有開頭
Set 表示這是類型 Set 的示例
第一個下劃線 _ 分隔符,在這個分隔符後面的,是 Set 類型的成員函數名
At 表示這是函數 At() 的示例,搭配前面的內容,則表示這是類型 Set 的成員函數 At() 的示例
第二個下劃線 _ 分隔符,在這個分隔符後面的內容,是示例代碼的額外說明
1 這是示例代碼的額外說明,也就是前面 “Example (1)” 括號裏的部分

另外,示例代碼中應該包含標準輸出內容,這樣便於讀者瞭解執行情況。標準輸出內容在函數內的最後,採用 // Output: 單獨起一行開頭,剩下的每一行標準輸出寫一行註釋。

相對應地,如果你想要給(不屬於任何一個類型的)函數寫示例的話,則去掉上文中關於 “類型” 的字段;如果你不需要示例的額外說明符,則去掉 “額外說明” 字段。比如說,我給類型 Opt 寫的示例就只有一個,在代碼中,只有一行:

func ExampleOpt() {
    ........
}

甚至連示例說明都沒有。

如果一個元素包含多個例子,那麼 godoc 會按照字母序對示例及其相應的說明排序。這也就是爲什麼我乾脆在 At() 函數中,示例標爲一二三四五的原因,因爲這是我希望讀者閱讀示例的順序。

在官網上發佈 godoc

好了,當你寫好了自己的 godoc 之後,總不是自己看自己自娛自樂吧,總歸是要發佈出來給大家看的。

其實發布也很簡單:當你將包含了 godox 的代碼 push 之後(比如發佈到 github 上),就可以在瀏覽器中輸入 https://godoc/org/${package路徑名}。比如 jsonvalue 的 Github 路徑(也等同於 import 路徑)爲 github.com/Andrew-M-C/go.jsonvalue,因此輸入 godoc.org/github.com/Andrew-M-C/go.jsonvalue

如果這是該頁面第一次進入,那麼 godoc.org 會首先獲取、解析和更新代碼倉庫中的文檔內容,並且格式化之後展示。在頁面的底部,會列出該 godoc 的更新時間。

如果你發現官網上的 godoc 內容已經落後了,那麼可以點 “Refresh now” 鏈接刷新它。

接下來更重要的是,把這份官網 godoc 的鏈接,附到你自己的 README 中。還是點上圖的 “Tools” 鏈接,就可以在新頁面中,看到相應的 godoc 徽標的鏈接了。有 htmlmarkdown 格式任君選擇。


本文章採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。

原作者: amc,歡迎轉載,但請註明出處。

原文標題:如何寫高大上的 godoc(Go 文檔)

發佈日期:2019/10/24

原文鏈接:https://cloud.tencent.com/developer/article/1526609

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章