go doc 命令可以打印附於Go語言程序 實體 上的文檔。我們可以通過把程序實體的標識符作為該命令的參數來達到查看其文檔的目的。
插播:所謂 Go語言的 程序實體,是指變量、常量、函數、結構體以及接口。而程序實體的 標識符 即是代表它們的名稱。標識符又分 非限定標識符 和 限定標識符。其中,限定標識符 一般用於表示某個代碼包中的程序實體或者某個結構體類型中的方法或字段。例如,標准庫代碼包 io 中的名為 EOF 的變量用限定標識符表示即 io.EOF。又例如,如果我有一個 sync.WaitGroup 類型的變量 wg 並且想調用它的 Add 方法,那么可以這樣寫 wg.Add()。其中,wg.Add 就是一個限定標識符,而后面的()則代表了調用操作。
下面說明怎樣使用 go doc 命令。先來看一下 go doc 命令可結束的標記。
表0-5 go doc命令的標記說明
標記名稱 | 標記描述 |
---|---|
-c | 加入此標記后會使 go doc 命令區分參數中字母的大小寫。默認情況下,命令是大小寫不敏感的。 |
-cmd | 加入此標記后會使 go doc 命令同時打印出main包中的可導出的程序實體(其名稱的首字母大寫)的文檔。默認情況下,這部分文檔是不會被打印出來的。 |
-u | 加入此標記后會使 go doc 命令同時打印出不可導出的程序實體(其名稱的首字母小寫)的文檔。默認情況下,這部分文檔是不會被打印出來的。 |
這幾個標記的意圖都非常簡單和明確,大家可以根據實際情況選用。
go doc 命令可以后跟一個或兩個參數。當然,我們也可以不附加任務參數。如果不附加參數,那么 go doc 命令會試圖打印出當前目錄所代表的代碼包的文檔及其中的包級程序實體的列表。
例如,我要在 goc2p 項目的 loadgen 代碼包所在目錄中運行 go doc 命令的話,那么就會是這樣:
hc@ubt:~/golang/goc2p/src/loadgen$ go doc package loadgen // import "loadgen" func NewGenerator( caller lib.Caller, timeoutNs time.Duration, lps uint32, durationNs time.Duration, resultCh chan *lib.CallResult) (lib.Generator, error)
如果你需要指定代碼包或程序實體,那么就需要在 go doc 命令后附上參數了。例如,只要我本地的 goc2p 項目的所在目錄存在於 GOPATH 環境變量中,我就可以在任意目錄中敲入 go doc loadgen。如此得到的輸出一定是與上面那個示例一致的。
看過 loadgen 代碼包中源碼的讀者會知道,其中只有一個可導出的程序實體,即 NewGenerator 函數。這也是上述示例中如此輸出的原因。該代碼包中的結構體類型 myGenerator 是不可導出,但是我們只需附加 -u 標記便可查看它的文檔了:
hc@ubt:~$ go doc -u loadgen.myGenerator type myGenerator struct { caller lib.Caller // 調用器。 timeoutNs time.Duration // 處理超時時間,單位:納秒。 lps uint32 // 每秒載荷量。 durationNs time.Duration // 負載持續時間,單位:納秒。 concurrency uint32 // 並發量。 tickets lib.GoTickets // Goroutine票池。 stopSign chan byte // 停止信號的傳遞通道。 cancelSign byte // 取消發送后續結果的信號。 endSign chan uint64 // 完結信號的傳遞通道,同時被用於傳遞調用執行計數。 callCount uint64 // 調用執行計數。 status lib.GenStatus // 狀態。 resultCh chan *lib.CallResult // 調用結果通道。 } // 載荷發生器的實現。 func (gen *myGenerator) Start() func (gen *myGenerator) Status() lib.GenStatus func (gen *myGenerator) Stop() (uint64, bool) func (gen *myGenerator) asyncCall() func (gen *myGenerator) genLoad(throttle <-chan time.Time) func (gen *myGenerator) handleStopSign(callCount uint64) func (gen *myGenerator) init() error func (gen *myGenerator) interact(rawReq *lib.RawReq) *lib.RawResp func (gen *myGenerator) sendResult(result *lib.CallResult) bool
如此一來,loadgen.myGenerator 類型的文檔、字段和方法都盡收眼底。注意,這里我們使用到了限定標識符。下面再進一步,如果你只想查看 loadgen.myGenerator 類型的 init 方法的文檔,那么只要續寫這個限定標識符就可以了,像這樣:
hc@ubt:~$ go doc -u loadgen.myGenerator.init func (gen *myGenerator) init() error // 初始化載荷發生器。
注意,結構體類型中的字段的文檔是無法被單獨打印的。另外,go doc 命令根據參數查找代碼包或程序實體的順序是:先 Go 語言根目錄(即 GOROOT 所環境變量指定的那個目錄)后工作區目錄(即 GOPATH 環境變量包含的那些目錄)。並且,在前者或后者中,go doc 命令的查找順序遵循字典序。因此,如果某個工作區目錄中的代碼包與標准庫中的包重名了,那么它是無法被打印出來的。go doc 命令只會打印出第一個匹配的代碼包或程序實體的文檔。
我們在前面說過,go doc 命令還可以接受兩個參數。這是一種更加精細的指定 代碼包 或 程序實體 的方式。一個顯著的區別是,如果你想打印標准庫代碼包 net/http 中的結構體類型 Request 的文檔,那么可以這樣敲入 go doc 命令:
go doc http.Request
注意,這里並沒有寫入 net/http 代碼包的導入路徑,而只是寫入了其中的最后一個元素 http。但是如果你把 http.Request 拆成兩個參數(即 http Request)的話,命令程序就會什么也查不到了。因為這與前一種用法的解析方式是不一樣的。正確的做法是,當你指定兩個參數時,作為第一個參數的代碼包名稱必須是完整的導入路徑,即:在敲入命令 go doc net/http Request 后,你會得到想要的結果。
最后,在給定兩個參數時,go doc 會打印出所有匹配的文檔,而不是像給定一個參數時那樣只打印出第一個匹配的文檔。這對於查找只有大小寫不同的多個方法(如 New 和 new)的文檔來說非常有用。
godoc
命令 godoc 是一個很強大的工具,同樣用於展示指定代碼包的文檔。在 Go 語言的 1.5 版本中,它是一個內置的標准命令。
該命令有兩種模式可供選擇。如果在執行命令時不加入 -http 標記,則該命令就以命令行模式運行。在打印純文本格式的文檔到標准輸出后,命令執行就結束了。比如,我們用命令行模式查看代碼包 fmt 的文檔:
hc@ubt:~$ godoc fmt
為了節省篇幅,我們在這里略去了文檔查詢結果。讀者可以自己運行一下上述命令。在該命令被執行之后,我們就可以看到編排整齊有序的文檔內容了。這包括代碼包 fmt 及其中所有可導出的包級程序實體的聲明、文檔和例子。
有時候我們只是想查看某一個函數或者結構體類型的文檔,那么我們可以將這個函數或者結構體的名稱加入命令的后面,像這樣:
hc@ubt:~$ godoc fmt Printf
或者:
hc@ubt:~$ godoc os File
如果我們想同時查看一個代碼包中的幾個函數的文檔,則僅需將函數或者結構體名稱追加到命令后面。比如我們要查看代碼包 fmt 中函數 Printf 和函數 Println 的文檔:
hc@ubt:~$ godoc fmt Printf Println
如果我們不但想在文檔中查看可導出的程序實體的聲明,還想看到它們的源碼,那么我們可以在執行 godoc 命令的時候加入標記 -src,比如這樣:
hc@ubt:~$ godoc -src fmt Printf
Go語言為程序使用示例代碼設立了專有的規則。我們在這里暫不討論這個規則的細節。只需要知道正因為有了這個專有規則,使得 godoc 命令可以根據這些規則提取相應的示例代碼並把它們加入到對應的文檔中。如果我們想在查看代碼包 net 中的結構體類型 Listener 的文檔的同時查看關於它的示例代碼,那么我們只需要在執行命令時加入標記 -ex。使用方法如下:
hc@ubt:~$ godoc -ex net/http FileServer
注意,我們在使用 godo c命令時,只能把代碼包和程序實體的標識符拆成兩個參數。也就是說,godoc 命令不支持前文所述的 go doc 命令的單參數用法。
在實際的Go語言環境中,我們可能會遇到一個命令源碼文件所產生的可執行文件與代碼包重名的情況。比如,這里介紹的標准命令 go 和官方代碼包 go。現在我們要明確的告訴 godoc 命令要查看可執行文件 go 的文檔,我們需要在名稱前加入 cmd/前綴:
hc@ubt:~$ godoc cmd/go
另外,如果我們想查看 HTML 格式的文檔,就需要加入標記 -html。當然,這樣在命令行模式下的查看效果是很差的。但是,如果仔細查看的話,可以在其中找到一些相應源碼的鏈接地址。
一般情況下,godoc 命令會去 Go 語言根目錄和環境變量 GOPATH 包含的工作區目錄中查找代碼包。我們可以通過加入標記 -goroot 來制定一個Go語言根目錄。這個被指定的 Go 語言根目錄僅被用於當次命令的執行。示例如下:
hc@ubt:~$ godoc -goroot="/usr/local/go" fmt
現在讓我們來看看另外一種模式。如果我們在執行命令時加上 -http 標記則會啟用另一模式。這種模式被叫做 Web 服務器模式,它以Web頁面的形式提供 Go 語言文檔。
我們使用如下命令啟動這個文檔 Web 服務器:
hc@ubt:~/golang/goc2p$ godoc -http=:6060
標記 -http 的值 :6060 表示啟動的 Web 服務器使用本機的 6060 端口。之后,我們就可以通過在網絡瀏覽器的地址欄中輸入 http://localhost:6060 來查看以網頁方式展現的 Go 文檔了。
圖0-1 本機的Go文檔Web服務首頁
這與 Go語言官方站點 的 Web 服務頁面如出一轍。這使得我們在不方便訪問 Go 語言官方站點的情況下也可以查看 Go 語言文檔。並且,更便利的是,通過本機的 Go 文檔 Web 服務,我們還可以查看所有本機工作區下的代碼的文檔。比如,goc2p 項目中的代碼包 pkgtool 的頁面如下圖:
圖0-2 goc2p 項目中的 pkgtool 包的 Go 文檔頁面
現在,我們在本機開啟 Go 文檔 Web 服務器,端口為 9090。命令如下:
hc@ubt:~$ godoc -http=:9090 -index
注意,要使用 -index 標記開啟搜索索引。這個索引會在服務器啟動時創建並維護。如果不加入此標記,那么無論在Web頁面還是命令行終端中都是無法進行查詢操作的。
索引中提供了標識符和全文本搜索信息(通過正則表達式為可搜索性提供支持)。全文本搜索結果顯示條目的最大數量可以通過標記 -maxresults 提供。標記 -maxresults 默認值是 10000。如果不想提供如此多的結果條目,可以設置小一些的值。甚至,如果不想提供全文本搜索結果,可以將標記 -maxresults 的值設置為0,這樣服務器就只會創建標識符索引,而根本不會創建全文本搜索索引了。標識符索引即為對程序實體名稱的索引。
正因為在使用了 -index 標記的情況下文檔服務器會在啟動時創建索引,所以在文檔服務器啟動之后還不能立即提供搜索服務,需要稍等片刻。在索引為被創建完畢之前,我們的搜索操作都會得到提示信息“Indexing in progress: result may be inaccurate”。
如果我們在本機用 godoc 命令啟動了 Go 文檔 Web 服務器,且 IP 地址為192.168.1.4、端口為 9090,那么我們就可以在另一個命令行終端甚至另一台能夠與本機聯通的計算機中通過如下命令進行查詢了。查詢命令如下:
hc@ubt:~$ godoc -q -server="192.168.1.4:9090" Listener
命令的最后為要查詢的內容,可以是任何你想搜索的字符串,而不僅限於代碼包、函數或者結構體的名稱。
標記 -q 開啟了遠程查詢的功能。而標記 -server="192.168.1.4:9090" 則指明了遠程文檔服務器的 IP 地址和端口號。實際上,如果不指明遠程查詢服務器的地址,那么該命令會自行將地址“:6060”和“golang.org”作為遠程查詢服務器的地址。這兩個地址即是默認的本機文檔Web站點地址和官方的文檔 Web 站點地址。所以執行如下命令我們也可以查詢到標准庫的信息:
hc@ubt:~$ godoc -q fmt
命令 godoc 還有很多可用的標記,但在通常情況下並不常用。讀者如果有興趣,可以在命令行環境下敲入 godoc 並查看其文檔。
摘自:
http://wiki.jikexueyuan.com/project/go-command-tutorial/0.5.html