如果導(dǎo)入包的名字沒有在文件中引用,就會產(chǎn)生一個編譯錯誤。但是,有時候必須導(dǎo)入一個包,這僅僅是為了利用它的副作用:對包級別的變量執(zhí)行初始化表達(dá)式求值,并執(zhí)行它的 init 函數(shù)。這里必須使用一個重命名導(dǎo)入,使用下劃線作為替代的名字。這表示導(dǎo)入的內(nèi)容為空白標(biāo)識符,通常情況下,空白標(biāo)識不可能被引用:
目前成都創(chuàng)新互聯(lián)公司已為上千余家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁空間、綿陽服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計、瑤海網(wǎng)站維護(hù)等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
import _ "image/png" // 注冊 PNG 解碼器
空白導(dǎo)入,多數(shù)情況下,使用空白引用導(dǎo)入額外的包,開啟主程序中可選的特性。
一些建議,關(guān)于遵從 Go 的習(xí)慣來給包和它的成員進(jìn)行命名。
包名使用簡短的名字,但是不要短到完全看不懂。
盡可能保持可讀性和無歧義。例如,不要把一個輔助工具包命名為 util,使用 imageutil 或 ioutil 這樣更具體和清晰的名字。
避免使用經(jīng)常用于相關(guān)局部變量的名字作為包名,或者迫使使用者使用重命名導(dǎo)入。例如,path 就要避免用作包名。
命名通常使用統(tǒng)一的形式,使用復(fù)數(shù)形式來避免和關(guān)鍵字的沖突。例如,標(biāo)準(zhǔn)包 bytes、errors、strings。
引用包的成員會帶上包名,所以設(shè)計成員名稱的時候,要考慮包名和成員名這兩部分協(xié)同一起表示的意義,而不只是成員名。
對于包導(dǎo)出的一個數(shù)據(jù)類型及其方法,通常有一個 New 函數(shù)用來創(chuàng)建實(shí)例。而導(dǎo)出的類型的名稱可能和包名重復(fù)。例如,template.Template 或 rand.Rand。
包中最重要的成員使用最簡單的命名。
go 工具將不同種類的工具集合并為一個命名集。它的命令行接口使用“瑞士軍刀”風(fēng)格,有十幾個子命令??梢赃\(yùn)行go help
來查看內(nèi)置文檔的索引:
bug start a bug report
build compile packages and dependencies
clean remove object files and cached files
doc show documentation for package or symbol
env print Go environment information
fix update packages to use new APIs
fmt gofmt (reformat) package sources
generate generate Go files by processing source
get download and install packages and dependencies
install compile and install packages and dependencies
list list packages or modules
mod module maintenance
run compile and run Go program
test test packages
tool run specified go tool
version print Go version
vet report likely mistakes in packages
環(huán)境變量 GOPATH 執(zhí)行工作空間的根。當(dāng)需要切換不同的工作空間時,更新 GOPATH 變量即可。
切換環(huán)境變量然后下載代碼:
$ export GOPATH=$HOME/gobook
$ go get gopl.io/...
命令最后的三個點(diǎn)的意義,go get 命令下一節(jié)會講。
GOPATH 有三個子目錄,分別用于存放不同類型的文件:
環(huán)境變量 GOROOT 指定 Go 發(fā)行版的根目錄,其中提供所有標(biāo)準(zhǔn)庫的包。用戶無須設(shè)置 GOROOT,因?yàn)槟J(rèn)情況下在安裝 Go 言語的時候會將其設(shè)置為安裝路徑。(如果機(jī)器上裝了多個版本的Go,就可以通過這個環(huán)境變量來切換了吧。不過Go目前需要使用多個版本的問題。)
命令 go env 可以查看環(huán)境變量。
go get 命令可以下載單一的包,也可以使用 ... 符號來下載子目錄或倉庫。并且還會計算并下載所有依賴的包。
讓包使用一個自定義的導(dǎo)入路徑,但是真實(shí)的代碼卻是由更通用的站點(diǎn)提供,例如 github。這只需要在頁面的 HTML 中添加如下的元數(shù)據(jù),它重定向 go 工具到實(shí)際托管地址的 Git 倉庫:
go get 指定 -u 參數(shù),將確保命令會訪問所有的包(無論本地是否已經(jīng)有了)更新到最新版本。如果沒有這個參數(shù),已經(jīng)存在在本地的包就做任何處理和確認(rèn)。
命令 go build 編譯每一個命令行參數(shù)中的包。如果包是一個庫,結(jié)果會被丟棄。如果是main包,則會創(chuàng)建可執(zhí)行程序。
命令 go run 則可以構(gòu)建之后直接運(yùn)行。適用于即用即拋型的程序。
第一個不是以 .go 結(jié)尾的參數(shù)會作為 Go 可執(zhí)行程序的參數(shù)列表的開始。
默認(rèn)情況下,go build 命令構(gòu)建所有需要的包以及它們所有的依賴,然后丟棄除了最終可執(zhí)行程序之外的所有編譯后的代碼。
命令 go install 和 go build 非常相似,區(qū)別是它會保存每一個包的編譯代碼和命令,而不丟棄。編譯后的包保存在 $GOPATH/pkg 目錄中。這樣,之后的 go build 和 go install 對于沒有改變的包和命令不需要再重新編譯,從而使后續(xù)的構(gòu)建更快完成。
go build 使用 -i 參數(shù),也會安裝那些編譯目標(biāo)依賴的且還未被安裝的代碼包。同樣是安裝到 pkg 目錄。
每一個導(dǎo)出的包成員的聲明以及包聲明自身應(yīng)該使用文檔注釋來描述它的目的和用途。Go 文檔注釋總是完整的語句,第一行通常是摘要說明,以被注釋者的名稱(比如函數(shù)名)開頭。
包聲明的前面的文檔注釋是對整個包進(jìn)行描述。它可以出現(xiàn)在任何一個文件里,但是每一個包里值能在一個文件開頭寫包的文檔注釋。比較長的包注釋可以使用一個單獨(dú)的注釋文件,文件名通常叫 doc.go。
go doc
go doc 工具輸出在命令行上指定的內(nèi)容的聲明和整個文檔注釋,可以是一個包、一個包成員、一個方法。
godoc
這是另一個工具,它提供一個 HTML 頁面,展示的內(nèi)容不少于 go doc 命令。
如果想瀏覽自己的包,可以在自己的工作區(qū)目錄中運(yùn)行 godoc。在執(zhí)行下面的命令后,在瀏覽器中訪問 http://localhost:8000/pkg
:
$ godoc -http :8000
還可以使用 -analysis=type 和 -analysis=pointer 命令行標(biāo)志參數(shù),用于打開文檔和代碼中關(guān)于靜態(tài)分析的結(jié)果。
導(dǎo)入路徑中包含 internal 的情況,會被特殊對待。這種包叫內(nèi)部包,內(nèi)部包只能被特定范圍內(nèi)的包導(dǎo)入,就是以這個內(nèi)部包的父目錄為根的目錄樹中的其他的包。
go list 工具上報可用包的信息。通過簡單的形式,go list 判斷一個包是否存在于工作區(qū)目錄中,如果存在就輸出它的導(dǎo)入路徑:
PS H:\Go\src\gopl\ch20> go list gopl/ch9/bank1
gopl/ch9/bank1
go list 命令的參數(shù)可以包含 “...” 通配符(類似于通配符星號的作用),用來匹配包的導(dǎo)入路徑中的任意字符串。這可以枚舉當(dāng)前工作區(qū)目錄下的所有的包: go list ...
,輸出的結(jié)果實(shí)在太多了。
下面是一個指定的目錄中的所有的包:
PS H:\Go\src\gopl\ch20> go list gopl/ch9/...
gopl/ch9/bank1
gopl/ch9/bank2
gopl/ch9/bank3
gopl/ch9/hacker
下面則是查找某個主題:
PS H:\Go\src\gopl\ch20> go list ...netcat...
gopl/ch8/netcat1
gopl/ch8/netcat2
gopl/ch8/netcat3
gopl/exercise8/e8/netcat
這里匹配的并不是包名,而是包的整個導(dǎo)入路徑。這也包括從工作區(qū)目錄為根開始的路徑所組成的字符串里的任何內(nèi)容。
go list 命令獲取每一個包的完整元數(shù)據(jù),而不僅僅是導(dǎo)入路徑,并且提供各種對于用戶或者其他工具可訪問的格式。
-json 標(biāo)記使 go list 以 JSON 格式輸出每一個包的完整記錄:
PS H:\Go\src\gopl\ch20> go list -json gopl/ch9/bank1
{
"Dir": "H:\\Go\\src\\gopl\\ch9\\bank1",
"ImportPath": "gopl/ch9/bank1",
"Name": "bank",
"Doc": "這是一個只有一個賬戶的并發(fā)安全銀行",
"Target": "H:\\Go\\pkg\\windows_amd64\\gopl\\ch9\\bank1.a",
"Root": "H:\\Go\\",
"Match": [
"gopl/ch9/bank1"
],
"Stale": true,
"StaleReason": "build ID mismatch",
"GoFiles": [
"main.go"
]
}
這里展開介紹其中三個字段的意義:
-f 標(biāo)記可以讓用戶通過 text/temple 包提供的模板語言來定制輸出的格式:
PS H:\Go\src\gopl\ch20> go list -json strconv
{
...
"Deps": [
"errors",
"internal/cpu",
"math",
"math/bits",
"unicode/utf8",
"unsafe"
],
...
}
PS H:\Go\src\gopl\ch20> go list -f "{{join .Deps \"" \""}}" strconv
errors internal/cpu math math/bits unicode/utf8 unsafe
PS H:\Go\src\gopl\ch20> go list -f '{{join .Deps \" \"}}' strconv
errors internal/cpu math math/bits unicode/utf8 unsafe
PS H:\Go\src\gopl\ch20> go list -f "{{join .Deps `` ``}}" strconv
errors internal/cpu math math/bits unicode/utf8 unsafe
PS H:\Go\src\gopl\ch20> go list -f '{{join .Deps ` `}}' strconv
errors internal/cpu math math/bits unicode/utf8 unsafe
由于這里 -f 的參數(shù)中有空格,必須要用引號包起來。而參數(shù)的內(nèi)容中還包含引號,所以這個參數(shù)很難寫。這里只給出幾個示例,具體什么規(guī)則講不清楚,大概有下面幾點(diǎn):
下面的命令輸出標(biāo)準(zhǔn)庫的 compress 子樹中每個包的直接導(dǎo)入記錄:
PS H:\Go\src\gopl\ch20> go list compress/...
compress/bzip2
compress/flate
compress/gzip
compress/lzw
compress/zlib
PS H:\Go\src\gopl\ch20> go list -f "{{.ImportPath}} -> {{join .Imports \"" \""}}" compress/...
compress/bzip2 -> bufio io sort
compress/flate -> bufio fmt io math math/bits sort strconv sync
compress/gzip -> bufio compress/flate encoding/binary errors fmt hash/crc32 io time
compress/lzw -> bufio errors fmt io
compress/zlib -> bufio compress/flate errors fmt hash hash/adler32 io
go list 命令對于一次性的交互查詢和構(gòu)建、測試腳本都非常有用。更多的參數(shù)信息,可以通過 go help list 來獲取。