鍍金池/ 教程/ GO/ go doc與godoc
go install
go clean
go list
go test
go doc與godoc
go build
go fix與go tool fix
go tool pprof
go run
go env
go tool cgo
標(biāo)準(zhǔn)命令詳解
go get
go vet與go tool vet

go doc與godoc

go doc

go doc命令可以打印附于Go語言程序?qū)嶓w上的文檔。我們可以通過把程序?qū)嶓w的標(biāo)識(shí)符作為該命令的參數(shù)來達(dá)到查看其文檔的目的。

插播:所謂Go語言的程序?qū)嶓w,是指變量、常量、函數(shù)、結(jié)構(gòu)體以及接口。而程序?qū)嶓w的標(biāo)識(shí)符即是代表它們的名稱。標(biāo)識(shí)符又分非限定標(biāo)識(shí)符和限定標(biāo)識(shí)符。其中,限定標(biāo)識(shí)符一般用于表示某個(gè)代碼包中的程序?qū)嶓w或者某個(gè)結(jié)構(gòu)體類型中的方法或字段。例如,標(biāo)準(zhǔn)庫代碼包io中的名為EOF的變量用限定標(biāo)識(shí)符表示即io.EOF。又例如,如果我有一個(gè)sync.WaitGroup類型的變量wg并且想調(diào)用它的Add方法,那么可以這樣寫wg.Add()。其中,wg.Add就是一個(gè)限定標(biāo)識(shí)符,而后面的()則代表了調(diào)用操作。

下面說明怎樣使用go doc命令。先來看一下go doc命令課結(jié)束的標(biāo)記。

表0-5 go doc命令的標(biāo)記說明

標(biāo)記名稱 標(biāo)記描述
-c 加入此標(biāo)記后會(huì)使go doc命令區(qū)分參數(shù)中字母的大小寫。默認(rèn)情況下,命令是大小寫不敏感的。
-cmd 加入此標(biāo)記后會(huì)使go doc命令同時(shí)打印出main包中的可導(dǎo)出的程序?qū)嶓w(其名稱的首字母大寫)的文檔。默認(rèn)情況下,這部分文檔是不會(huì)被打印出來的。
-u 加入此標(biāo)記后會(huì)使go doc命令同時(shí)打印出不可導(dǎo)出的程序?qū)嶓w(其名稱的首字母小寫)的文檔。默認(rèn)情況下,這部分文檔是不會(huì)被打印出來的。

這幾個(gè)標(biāo)記的意圖都非常簡(jiǎn)單和明確,大家可以根據(jù)實(shí)際情況選用。

go doc命令可以后跟一個(gè)或兩個(gè)參數(shù)。當(dāng)然,我們也可以不附加任務(wù)參數(shù)。如果不附加參數(shù),那么go doc命令會(huì)試圖打印出當(dāng)前目錄所代表的代碼包的文檔及其中的包級(jí)程序?qū)嶓w的列表。

例如,我要在goc2p項(xiàng)目的loadgen代碼包所在目錄中運(yùn)行go doc命令的話,那么就會(huì)是這樣:

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)

如果你需要指定代碼包或程序?qū)嶓w,那么就需要在go doc命令后附上參數(shù)了。例如,只要我本地的goc2p項(xiàng)目的所在目錄存在于GOPATH環(huán)境變量中,我就可以在任意目錄中敲入go doc loadgen。如此得到的輸出一定是與上面那個(gè)示例一致的。

看過loadgen代碼包中源碼的讀者會(huì)知道,其中只有一個(gè)可導(dǎo)出的程序?qū)嶓w,即NewGenerator函數(shù)。這也是上述示例中如此輸出的原因。該代碼包中的結(jié)構(gòu)體類型myGenerator是不可導(dǎo)出,但是我們只需附加-u標(biāo)記便可查看它的文檔了:

hc@ubt:~$ go doc -u loadgen.myGenerator
type myGenerator struct {
    caller      lib.Caller           // 調(diào)用器。
    timeoutNs   time.Duration        // 處理超時(shí)時(shí)間,單位:納秒。
    lps         uint32               // 每秒載荷量。
    durationNs  time.Duration        // 負(fù)載持續(xù)時(shí)間,單位:納秒。
    concurrency uint32               // 并發(fā)量。
    tickets     lib.GoTickets        // Goroutine票池。
    stopSign    chan byte            // 停止信號(hào)的傳遞通道。
    cancelSign  byte                 // 取消發(fā)送后續(xù)結(jié)果的信號(hào)。
    endSign     chan uint64          // 完結(jié)信號(hào)的傳遞通道,同時(shí)被用于傳遞調(diào)用執(zhí)行計(jì)數(shù)。
    callCount   uint64               // 調(diào)用執(zhí)行計(jì)數(shù)。
    status      lib.GenStatus        // 狀態(tài)。
    resultCh    chan *lib.CallResult // 調(diào)用結(jié)果通道。
}

    載荷發(fā)生器的實(shí)現(xiàn)。

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類型的文檔、字段和方法都盡收眼底。注意,這里我們使用到了限定標(biāo)識(shí)符。下面再進(jìn)一步,如果你只想查看loadgen.myGenerator類型的init方法的文檔,那么只要續(xù)寫這個(gè)限定標(biāo)識(shí)符就可以了,像這樣:

hc@ubt:~$ go doc -u loadgen.myGenerator.init
func (gen *myGenerator) init() error

    初始化載荷發(fā)生器。

注意,結(jié)構(gòu)體類型中的字段的文檔是無法被單獨(dú)打印的。另外,go doc命令根據(jù)參數(shù)查找代碼包或程序?qū)嶓w的順序是:先Go語言根目錄(即GOROOT所環(huán)境變量指定的那個(gè)目錄)后工作區(qū)目錄(即GOPATH環(huán)境變量包含的那些目錄)。并且,在前者或后者中,go doc命令的查找順序遵循字典序。因此,如果某個(gè)工作區(qū)目錄中的代碼包與標(biāo)準(zhǔn)庫中的包重名了,那么它是無法被打印出來的。go doc命令只會(huì)打印出第一個(gè)匹配的代碼包或程序?qū)嶓w的文檔。

我們?cè)谇懊嬲f過,go doc命令還可以接受兩個(gè)參數(shù)。這是一種更加精細(xì)的指定代碼包或程序?qū)嶓w的方式。一個(gè)顯著的區(qū)別是,如果你想打印標(biāo)準(zhǔn)庫代碼包net/http中的結(jié)構(gòu)體類型Request的文檔,那么可以這樣敲入go doc命令:

go doc http.Request

注意,這里并沒有寫入net/http代碼包的導(dǎo)入路徑,而只是寫入了其中的最后一個(gè)元素http。但是如果你把http.Request拆成兩個(gè)參數(shù)(即http Request)的話,命令程序就會(huì)什么也查不到了。因?yàn)檫@與前一種用法的解析方式是不一樣的。正確的做法是,當(dāng)你指定兩個(gè)參數(shù)時(shí),作為第一個(gè)參數(shù)的代碼包名稱必須是完整的導(dǎo)入路徑,即:在敲入命令go doc net/http Request后,你會(huì)得到想要的結(jié)果。

最后,在給定兩個(gè)參數(shù)時(shí),go doc會(huì)打印出所有匹配的文檔,而不是像給定一個(gè)參數(shù)時(shí)那樣只打印出第一個(gè)匹配的文檔。這對(duì)于查找只有大小寫不同的多個(gè)方法(如Newnew)的文檔來說非常有用。

godoc

命令godoc是一個(gè)很強(qiáng)大的工具,同樣用于展示指定代碼包的文檔。在Go語言的1.5版本中,它是一個(gè)內(nèi)置的標(biāo)準(zhǔn)命令。

該命令有兩種模式可供選擇。如果在執(zhí)行命令時(shí)不加入-http標(biāo)記,則該命令就以命令行模式運(yùn)行。在打印純文本格式的文檔到標(biāo)準(zhǔn)輸出后,命令執(zhí)行就結(jié)束了。比如,我們用命令行模式查看代碼包fmt的文檔:

hc@ubt:~$ godoc fmt

為了節(jié)省篇幅,我們?cè)谶@里略去了文檔查詢結(jié)果。讀者可以自己運(yùn)行一下上述命令。在該命令被執(zhí)行之后,我們就可以看到編排整齊有序的文檔內(nèi)容了。這包括代碼包fmt及其中所有可導(dǎo)出的包級(jí)程序?qū)嶓w的聲明、文檔和例子。

有時(shí)候我們只是想查看某一個(gè)函數(shù)或者結(jié)構(gòu)體類型的文檔,那么我們可以將這個(gè)函數(shù)或者結(jié)構(gòu)體的名稱加入命令的后面,像這樣:

hc@ubt:~$ godoc fmt Printf

或者:

hc@ubt:~$ godoc os File

如果我們想同時(shí)查看一個(gè)代碼包中的幾個(gè)函數(shù)的文檔,則僅需將函數(shù)或者結(jié)構(gòu)體名稱追加到命令后面。比如我們要查看代碼包fmt中函數(shù)Printf和函數(shù)Println的文檔:

hc@ubt:~$ godoc fmt Printf Println

如果我們不但想在文檔中查看可導(dǎo)出的程序?qū)嶓w的聲明,還想看到它們的源碼,那么我們可以在執(zhí)行godoc命令的時(shí)候加入標(biāo)記-src,比如這樣:

hc@ubt:~$ godoc -src fmt Printf

Go語言為程序使用示例代碼設(shè)立了專有的規(guī)則。我們?cè)谶@里暫不討論這個(gè)規(guī)則的細(xì)節(jié)。只需要知道正因?yàn)橛辛诉@個(gè)專有規(guī)則,使得godoc命令可以根據(jù)這些規(guī)則提取相應(yīng)的示例代碼并把它們加入到對(duì)應(yīng)的文檔中。如果我們想在查看代碼包net中的結(jié)構(gòu)體類型Listener的文檔的同時(shí)查看關(guān)于它的示例代碼,那么我們只需要在執(zhí)行命令時(shí)加入標(biāo)記-ex。使用方法如下:

hc@ubt:~$ godoc -ex net/http FileServer

注意,我們?cè)谑褂?code>godoc命令時(shí),只能把代碼包和程序?qū)嶓w的標(biāo)識(shí)符拆成兩個(gè)參數(shù)。也就是說,godoc命令不支持前文所述的go doc命令的單參數(shù)用法。

在實(shí)際的Go語言環(huán)境中,我們可能會(huì)遇到一個(gè)命令源碼文件所產(chǎn)生的可執(zhí)行文件與代碼包重名的情況。比如,這里介紹的標(biāo)準(zhǔn)命令go和官方代碼包go?,F(xiàn)在我們要明確的告訴godoc命令要查看可執(zhí)行文件go的文檔,我們需要在名稱前加入cmd/前綴:

hc@ubt:~$ godoc cmd/go

另外,如果我們想查看HTML格式的文檔,就需要加入標(biāo)記-html。當(dāng)然,這樣在命令行模式下的查看效果是很差的。但是,如果仔細(xì)查看的話,可以在其中找到一些相應(yīng)源碼的鏈接地址。

一般情況下,godoc命令會(huì)去Go語言根目錄和環(huán)境變量GOPATH包含的工作區(qū)目錄中查找代碼包。我們可以通過加入標(biāo)記-goroot來制定一個(gè)Go語言根目錄。這個(gè)被指定的Go語言根目錄僅被用于當(dāng)次命令的執(zhí)行。示例如下:

hc@ubt:~$ godoc -goroot="/usr/local/go" fmt

現(xiàn)在讓我們來看看另外一種模式。如果我們?cè)趫?zhí)行命令時(shí)加上-http標(biāo)記則會(huì)啟用另一模式。這種模式被叫做Web服務(wù)器模式,它以Web頁面的形式提供Go語言文檔。

我們使用如下命令啟動(dòng)這個(gè)文檔Web服務(wù)器:

hc@ubt:~/golang/goc2p$ godoc -http=:6060

標(biāo)記-http的值:6060表示啟動(dòng)的Web服務(wù)器使用本機(jī)的6060端口。之后,我們就可以通過在網(wǎng)絡(luò)瀏覽器的地址欄中輸入http://localhost:6060來查看以網(wǎng)頁方式展現(xiàn)的Go文檔了。

http://wiki.jikexueyuan.com/project/go-command-tutorial/images/0-1.png" alt="本機(jī)的Go文檔Web服務(wù)首頁" />

圖0-1 本機(jī)的Go文檔Web服務(wù)首頁

這與Go語言官方站點(diǎn)的Web服務(wù)頁面如出一轍。這使得我們?cè)诓环奖阍L問Go語言官方站點(diǎn)的情況下也可以查看Go語言文檔。并且,更便利的是,通過本機(jī)的Go文檔Web服務(wù),我們還可以查看所有本機(jī)工作區(qū)下的代碼的文檔。比如,goc2p項(xiàng)目中的代碼包pkgtool的頁面如下圖:

http://wiki.jikexueyuan.com/project/go-command-tutorial/images/0-2.png" alt="goc2p項(xiàng)目中的pkgtool包的Go文檔頁面" />

圖0-2 goc2p項(xiàng)目中的pkgtool包的Go文檔頁面

現(xiàn)在,我們?cè)诒緳C(jī)開啟Go文檔Web服務(wù)器,端口為9090。命令如下:

hc@ubt:~$ godoc -http=:9090 -index

注意,要使用-index標(biāo)記開啟搜索索引。這個(gè)索引會(huì)在服務(wù)器啟動(dòng)時(shí)創(chuàng)建并維護(hù)。如果不加入此標(biāo)記,那么無論在Web頁面還是命令行終端中都是無法進(jìn)行查詢操作的。

索引中提供了標(biāo)識(shí)符和全文本搜索信息(通過正則表達(dá)式為可搜索性提供支持)。全文本搜索結(jié)果顯示條目的最大數(shù)量可以通過標(biāo)記-maxresults提供。標(biāo)記-maxresults默認(rèn)值是10000。如果不想提供如此多的結(jié)果條目,可以設(shè)置小一些的值。甚至,如果不想提供全文本搜索結(jié)果,可以將標(biāo)記-maxresults的值設(shè)置為0,這樣服務(wù)器就只會(huì)創(chuàng)建標(biāo)識(shí)符索引,而根本不會(huì)創(chuàng)建全文本搜索索引了。標(biāo)識(shí)符索引即為對(duì)程序?qū)嶓w名稱的索引。

正因?yàn)樵谑褂昧?code>-index標(biāo)記的情況下文檔服務(wù)器會(huì)在啟動(dòng)時(shí)創(chuàng)建索引,所以在文檔服務(wù)器啟動(dòng)之后還不能立即提供搜索服務(wù),需要稍等片刻。在索引為被創(chuàng)建完畢之前,我們的搜索操作都會(huì)得到提示信息“Indexing in progress: result may be inaccurate”。

如果我們?cè)诒緳C(jī)用godoc命令啟動(dòng)了Go文檔Web服務(wù)器,且IP地址為192.168.1.4、端口為9090,那么我們就可以在另一個(gè)命令行終端甚至另一臺(tái)能夠與本機(jī)聯(lián)通的計(jì)算機(jī)中通過如下命令進(jìn)行查詢了。查詢命令如下:

    hc@ubt:~$ godoc -q -server="192.168.1.4:9090" Listener

命令的最后為要查詢的內(nèi)容,可以是任何你想搜索的字符串,而不僅限于代碼包、函數(shù)或者結(jié)構(gòu)體的名稱。

標(biāo)記-q開啟了遠(yuǎn)程查詢的功能。而標(biāo)記-server="192.168.1.4:9090"則指明了遠(yuǎn)程文檔服務(wù)器的IP地址和端口號(hào)。實(shí)際上,如果不指明遠(yuǎn)程查詢服務(wù)器的地址,那么該命令會(huì)自行將地址“:6060”和“golang.org”作為遠(yuǎn)程查詢服務(wù)器的地址。這兩個(gè)地址即是默認(rèn)的本機(jī)文檔Web站點(diǎn)地址和官方的文檔Web站點(diǎn)地址。所以執(zhí)行如下命令我們也可以查詢到標(biāo)準(zhǔn)庫的信息:

hc@ubt:~$ godoc -q fmt

命令godoc還有很多可用的標(biāo)記,但在通常情況下并不常用。讀者如果有興趣,可以在命令行環(huán)境下敲入godoc并查看其文檔。

至于怎樣才能寫出優(yōu)秀的代碼包文檔,我在《Go并發(fā)編程實(shí)戰(zhàn)》的5.2節(jié)中做了詳細(xì)說明。

上一篇:go clean下一篇:go list