鍍金池/ 教程/ GO/ go list
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 list

go list命令的作用是列出指定的代碼包的信息。與其他命令相同,我們需要以代碼包導(dǎo)入路徑的方式給定代碼包。被給定的代碼包可以有多個。這些代碼包對應(yīng)的目錄中必須直接保存有Go語言源碼文件,其子目錄中的文件不算在內(nèi)。否則,代碼包將被看做是不完整的?,F(xiàn)在我們來試用一下:

hc@ubt:~$ go list cnet/ctcp pkgtool
cnet/ctcp
pkgtool

我們看到,在不加任何標(biāo)記的情況下,命令的結(jié)果信息中只包含了我們指定的代碼包的導(dǎo)入路徑。我們剛剛提到,作為參數(shù)的代碼包必須是完整的代碼包。例如:

hc@ubt:~$ go list cnet pkgtool
can't load package: package cnet: no buildable Go source files in /home/hc/golang/goc2p/src/cnet/
pkgtool

這時,go list命令報告了一個錯誤——代碼包cnet對應(yīng)的目錄下沒有Go源碼文件。但是命令還是把代碼包pkgtool的導(dǎo)入路徑打印出來了。然而,當(dāng)我們在執(zhí)行go list命令并加入標(biāo)記-e時,即使參數(shù)中包含有不完整的代碼包,命令也不會提示錯誤。示例如下:

hc@ubt:~$ go list -e cnet pkgtool
cnet
pkgtool

標(biāo)記-e的作用是以容錯模式加載和分析指定的代碼包。在這種情況下,命令程序如果在加載或分析的過程中遇到錯誤只會在內(nèi)部記錄一下,而不會直接把錯誤信息打印出來。我們?yōu)榱丝吹藉e誤信息可以使用-json標(biāo)記。這個標(biāo)記的作用是把代碼包的結(jié)構(gòu)體實例用JSON的樣式打印出來。

這里解釋一下,JSON的全稱是Javascript Object Notation。它一種輕量級的承載數(shù)據(jù)的格式。JSON的優(yōu)勢在于語法簡單、短小精悍,且非常易于處理。JSON還是一種純文本格式,獨立于編程語言。正因為如此,得到了絕大多數(shù)編程語言和瀏覽器的支持,應(yīng)用非常廣泛。Go語言當(dāng)然也不例外,在它的標(biāo)準(zhǔn)庫中有專門用于處理和轉(zhuǎn)換JSON格式的數(shù)據(jù)的代碼包encoding/json。關(guān)于JSON格式的具體內(nèi)容,讀者可以去它的官方網(wǎng)站查看說明。

在了解了這些基本概念之后,我們來試用一下-json標(biāo)記。示例如下:

hc@ubt:~$ go list -e -json cnet
    {
            "Dir": "/home/hc/golang/goc2p/src/cnet",
            "ImportPath": "cnet",
            "Stale": true,
            "Root": "/home/hc/golang/goc2p",
            "Incomplete": true,
            "Error": {
                    "ImportStack": [
                            "cnet"
                    ],
                    "Pos": "",
                    "Err": "no Go source files in /home/hc/golang/goc2p/src/cnet"
            }
    }

在上述JSON格式的代碼包信息中,對于結(jié)構(gòu)體中的字段的顯示是不完整的。因為命令程序認(rèn)為我們指定cnet就是不完整的。在名為Error的字段中,我們可以看到具體說明。Error字段的內(nèi)容其實也是一個結(jié)構(gòu)體。在JSON格式下,這種嵌套的結(jié)構(gòu)體被完美的展現(xiàn)了出來。Error字段所指代的結(jié)構(gòu)體實例的Err字段說明了cnet不完整的原因。這與我們在沒有使用-e標(biāo)記的情況下所打印出來的錯誤提示信息是一致的。我們再來看Incomplete字段。它的值為true。這同樣說明cnet是一個不完整的代碼包。

實際上,在從這個代碼包結(jié)構(gòu)體實例到JSON格式文本的轉(zhuǎn)換過程中,所有的值為其類型的空值的字段都已經(jīng)被忽略了。

現(xiàn)在我們使用帶-json標(biāo)記的go list命令列出代碼包cnet/ctcp的信息:

hc@ubt:~$ go list -json cnet/ctcp
{
    "Dir": "/home/hc/golang/github/goc2p/src/cnet/ctcp",
    "ImportPath": "cnet/ctcp",
    "Name": "ctcp",
    "Target": "/home/hc/golang/github/goc2p/pkg/darwin_amd64/cnet/ctcp.a",
    "Stale": true,
    "Root": "/home/hc/golang/github/goc2p",
    "GoFiles": [
        "base.go",
        "tcp.go"
    ],
    "Imports": [
        "bufio",
        "bytes",
        "errors",
        "logging",
        "net",
        "sync",
        "time"
    ],
    "Deps": [
        "bufio",
        "bytes",
        "errors",
        "fmt",
        "internal/singleflight",
        "io",
        "log",
        "logging",
        "math",
        "math/rand",
        "net",
        "os",
        "reflect",
        "runtime",
        "runtime/cgo",
        "sort",
        "strconv",
        "strings",
        "sync",
        "sync/atomic",
        "syscall",
        "time",
        "unicode",
        "unicode/utf8",
        "unsafe"
    ],
    "TestGoFiles": [
        "tcp_test.go"
    ],
    "TestImports": [
        "bytes",
        "fmt",
        "net",
        "runtime",
        "strings",
        "sync",
        "testing",
        "time"
    ]
}

由于cnet/ctcp包是一個完整有效的代碼包,所以我們不使用-e標(biāo)記也是沒有問題的。在上面打印的cnet/ctcp包的信息中沒有Incomplete字段。這是因為完整的代碼包中的Incomplete字段的其類型的空值false。它已經(jīng)在轉(zhuǎn)換過程中被忽略掉了。另外,在cnet/ctcp包的信息中我們看到了很多其它的字段?,F(xiàn)在我就來看看在Go命令程序中的代碼包結(jié)構(gòu)體都有哪些公開的字段。如下表。

表0-7 代碼包結(jié)構(gòu)體中的基本字段

字段名稱 字段類型 字段描述
Dir 字符串(string) 代碼包對應(yīng)的目錄。
ImportPath 字符串(string) 代碼包的導(dǎo)入路徑。
ImportComment 字符串(string) 代碼包聲明語句右邊的用于自定義導(dǎo)入路徑的注釋。
Name 字符串(string) 代碼包的名稱。
Doc 字符串(string) 代碼包的文檔字符串。
Target 字符串(string) 代碼包的安裝路徑。
Shlib 字符串(string) 包含該代碼包的共享庫(shared library)的名稱。
Goroot 布爾(bool) 該代碼包是否在Go語言安裝目錄下。
Standard 布爾(bool) 該代碼包是否屬于標(biāo)準(zhǔn)庫的一部分。
Stale 布爾(bool) 該代碼包的最新代碼是否未被安裝。
Root 字符串(string) 該代碼包所屬的工作區(qū)或Go安裝目錄的路徑。

表0-8 代碼包結(jié)構(gòu)體中與源碼文件有關(guān)的字段

字段名稱 字段類型 字段描述
GoFiles 字符串切片([]string) Go源碼文件的列表。不包含導(dǎo)入了代碼包“C”的源碼文件和測試源碼文件。
CgoFiles 字符串切片([]string) 導(dǎo)入了代碼包“C”的源碼文件的列表。
IgnoredGoFiles 字符串切片([]string) 忽略編譯的源碼文件的列表。
CFiles 字符串切片([]string) 名稱中有“.c”后綴的源碼文件的列表。
CXXFiles 字符串切片([]string) 名稱中有“.cc”、“.cxx”或“.cpp”后綴的源碼文件的列表。
MFiles 字符串切片([]string) 名稱中“.m”后綴的源碼文件的列表。
HFiles 字符串切片([]string) 名稱中有“.h”后綴的源碼文件的列表。
SFiles 字符串切片([]string) 名稱中有“.s”后綴的源碼文件的列表。
SwigFiles 字符串切片([]string) 名稱中有“.swig”后綴的文件的列表。
SwigCXXFiles 字符串切片([]string) 名稱中有“.swigcxx”后綴的文件的列表。
SysoFiles 字符串切片([]string) 名稱中有“.syso”后綴的文件的列表。這些文件是需要被加入到歸檔文件中的。

表0-9 代碼包結(jié)構(gòu)體中與Cgo指令有關(guān)的字段

字段名稱 字段類型 字段描述
CgoCFLAGS 字符串切片([]string) 需要傳遞給C編譯器的標(biāo)記的列表。針對Cgo。
CgoCPPFLAGS 字符串切片([]string) 需要傳遞給C預(yù)處理器的標(biāo)記的列表。針對Cgo。
CgoCXXFLAGS 字符串切片([]string) 需要傳遞給C++編譯器的標(biāo)記的列表。針對Cgo。
CgoLDFLAGS 字符串切片([]string) 需要傳遞給鏈接器的標(biāo)記的列表。針對Cgo。
CgoPkgConfig 字符串切片([]string) pkg-config的名稱的列表。針對Cgo。

表0-10 代碼包結(jié)構(gòu)體中與依賴信息有關(guān)的字段

字段名稱 字段類型 字段描述
Imports 字符串切片([]string) 該代碼包中的源碼文件顯式導(dǎo)入的依賴包的導(dǎo)入路徑的列表。
Deps 字符串切片([]string) 所有的依賴包(包括間接依賴)的導(dǎo)入路徑的列表。

表0-11 代碼包結(jié)構(gòu)體中與錯誤信息有關(guān)的字段

字段名稱 字段類型 字段描述
Incomplete 布爾(bool) 代碼包是否是完整的,也即在載入或分析代碼包及其依賴包時是否有錯誤發(fā)生。
Error *PackageError類型 載入或分析代碼包時發(fā)生的錯誤。
DepsErrors []*PackageError類型 載入或分析依賴包時發(fā)生的錯誤。

表0-12 代碼包結(jié)構(gòu)體中與測試源碼文件有關(guān)的字段

字段名稱 字段類型 字段描述
TestGoFiles 字符串切片([]string) 代碼包中的測試源碼文件的名稱列表。
TestImports 字符串切片([]string) 代碼包中的測試源碼文件顯示導(dǎo)入的依賴包的導(dǎo)入路徑的列表。
XTestGoFiles 字符串切片([]string) 代碼包中的外部測試源碼文件的名稱列表。
XTestImports 字符串切片([]string) 代碼包中的外部測試源碼文件顯示導(dǎo)入的依賴包的導(dǎo)入路徑的列表。

代碼包結(jié)構(gòu)體中定義的字段很多,但有些時候我們只需要查看其中的一些字段。那要怎么做呢?標(biāo)記-f可以滿足這個需求。比如這樣:

hc@ubt:~$ go list -f {{.ImportPath}} cnet/ctcp
cnet/ctcp

實際上,-f標(biāo)記的默認(rèn)值就是{{.ImportPath}}。這也正是我們在使用不加任何標(biāo)記的go list命令時依然能看到指定代碼包的導(dǎo)入路徑的原因了。

標(biāo)記-f的值需要滿足標(biāo)準(zhǔn)庫的代碼包`text/template中定義的語法。比如,{{.S}}代表根結(jié)構(gòu)體的S字段的值。在go list命令的場景下,這個根結(jié)構(gòu)體就是指定的代碼包所對應(yīng)的結(jié)構(gòu)體。如果S字段的值也是一個結(jié)構(gòu)體的話,那么{{.S.F}}就代表根結(jié)構(gòu)體的S字段的值中的F字段的值。如果我們要查看cnet/ctcp包中的命令源碼文件和庫源碼文件的列表,可以這樣使用-f標(biāo)記:

hc@ubt:~$ go list -f {{.GoFiles}} cnet/ctcp
[base.go tcp.go]

如果我們想查看不完整的代碼包cnet的錯誤提示信息,還可以這樣:

hc@ubt:~$ go list -e -f {{.Error.Err}} cnet
no buildable Go source files in /home/hc/golang/goc2p/src/cnet

我們還可以利用代碼包text/template中定義的強大語法讓go list命令輸出定制化更高的代碼包信息。比如:

hc@ubt:~$ go list -e -f 'The package {{.ImportPath}} is {{if .Incomplete}}incomplete!{{else}}complete.{{end}}' cnet
The package cnet is incomplete!

```bash 
hc@ubt:~$ go list -f 'The imports of package {{.ImportPath}} is [{{join .Imports ", "}}].' cnet/ctcp
The imports of package cnet/ctcp is [bufio, bytes, errors, logging, net, sync, time].

其中,join是命令程序在text/template包原有語法之上自定義的語法,在底層使用標(biāo)準(zhǔn)庫代碼包strings中的Join函數(shù)。關(guān)于更多的語法規(guī)則,請讀者查看代碼包text/template的相關(guān)文檔。

另外,-tags標(biāo)記也可以被go list接受。它與我們在講go build命令時提到的-tags標(biāo)記是一致的。讀者可以查看代碼包`go/build``的文檔以了解細節(jié)。

go list命令很有用。它可以為我們提供指定代碼包的更深層次的信息。這些信息往往是我們無法從源碼文件中直觀看到的。

上一篇:go doc與godoc下一篇:go vet與go tool vet