gopl 包和工具

空導入

若是導入包的名字沒有在文件中引用,就會產生一個編譯錯誤。可是,有時候必須導入一個包,這僅僅是爲了利用它的反作用:對包級別的變量執行初始化表達式求值,並執行它的 init 函數。這裏必須使用一個重命名導入,使用下劃線做爲替代的名字。這表示導入的內容爲空白標識符,一般狀況下,空白標識不可能被引用:html

import _ "image/png" // 註冊 PNG 解碼器

空白導入,多數狀況下,使用空白引用導入額外的包,開啓主程序中可選的特性。 git

命名

一些建議,關於聽從 Go 的習慣來給包和它的成員進行命名。 github

包的命名

包名使用簡短的名字,可是不要短到徹底看不懂。
儘量保持可讀性和無歧義。例如,不要把一個輔助工具包命名爲 util,使用 imageutil 或 ioutil 這樣更具體和清晰的名字。
避免使用常常用於相關局部變量的名字做爲包名,或者迫使使用者使用重命名導入。例如,path 就要避免用做包名。
命名一般使用統一的形式,使用複數形式來避免和關鍵字的衝突。例如,標準包 bytes、errors、strings。 golang

包成員的命名

引用包的成員會帶上包名,因此設計成員名稱的時候,要考慮包名和成員名這兩部分協同一塊兒表示的意義,而不僅是成員名。
對於包導出的一個數據類型及其方法,一般有一個 New 函數用來建立實例。而導出的類型的名稱可能和包名重複。例如,template.Template 或 rand.Rand。
包中最重要的成員使用最簡單的命名。 json

go 工具

go 工具將不一樣種類的工具集合併爲一個命名集。它的命令行接口使用「瑞士軍刀」風格,有十幾個子命令。能夠運行go help來查看內置文檔的索引:windows

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

工做空間的組織

環境變量 GOPATH 執行工做空間的根。當須要切換不一樣的工做空間時,更新 GOPATH 變量便可。
切換環境變量而後下載代碼:瀏覽器

$ export GOPATH=$HOME/gobook
$ go get gopl.io/...

命令最後的三個點的意義,go get 命令下一節會講。安全

GOPATH 有三個子目錄,分別用於存放不一樣類型的文件:併發

  • src:源碼文件。每個包在一個目錄中
  • pkg:歸檔文件。構建工具存儲編譯後的包的位置,參考後面的 go install 命令
  • bin:可執行文件。許多用戶會將該目錄添加到可執行程序的搜索列表中

環境變量 GOROOT 指定 Go 發行版的根目錄,其中提供全部標準庫的包。用戶無須設置 GOROOT,由於默認狀況下在安裝 Go 言語的時候會將其設置爲安裝路徑。(若是機器上裝了多個版本的Go,就能夠經過這個環境變量來切換了吧。不過Go目前須要使用多個版本的問題。ide

命令 go env 能夠查看環境變量。

包的下載

go get 命令能夠下載單一的包,也可使用 ... 符號來下載子目錄或倉庫。而且還會計算並下載全部依賴的包。

讓包使用一個自定義的導入路徑,可是真實的代碼倒是由更通用的站點提供,例如 github。這隻須要在頁面的 HTML 中添加以下的元數據,它重定向 go 工具到實際託管地址的 Git 倉庫:

<meta name="go-import" content="golang.org/x/net git https://go.googlesource.com/net">

go get 指定 -u 參數,將確保命令會訪問全部的包(不管本地是否已經有了)更新到最新版本。若是沒有這個參數,已經存在在本地的包就作任何處理和確認。

包的構建

命令 go build 編譯每個命令行參數中的包。若是包是一個庫,結果會被丟棄。若是是main包,則會建立可執行程序。
命令 go run 則能夠構建以後直接運行。適用於即用即拋型的程序。
第一個不是以 .go 結尾的參數會做爲 Go 可執行程序的參數列表的開始。

默認狀況下,go build 命令構建全部須要的包以及它們全部的依賴,而後丟棄除了最終可執行程序以外的全部編譯後的代碼。
命令 go install 和 go build 很是類似,區別是它會保存每個包的編譯代碼和命令,而不丟棄。編譯後的包保存在 $GOPATH/pkg 目錄中。這樣,以後的 go build 和 go install 對於沒有改變的包和命令不須要再從新編譯,從而使後續的構建更快完成。
go build 使用 -i 參數,也會安裝那些編譯目標依賴的且還未被安裝的代碼包。一樣是安裝到 pkg 目錄。

包的文檔化

每個導出的包成員的聲明以及包聲明自身應該使用文檔註釋來描述它的目的和用途。Go 文檔註釋老是完整的語句,第一行一般是摘要說明,以被註釋者的名稱(好比函數名)開頭。
包聲明的前面的文檔註釋是對整個包進行描述。它能夠出如今任何一個文件裏,可是每個包裏值能在一個文件開頭寫包的文檔註釋。比較長的包註釋可使用一個單獨的註釋文件,文件名一般叫 doc.go。

go doc
go doc 工具輸出在命令行上指定的內容的聲明和整個文檔註釋,能夠是一個包、一個包成員、一個方法。

godoc
這是另外一個工具,它提供一個 HTML 頁面,展現的內容很多於 go doc 命令。
若是想瀏覽本身的包,能夠在本身的工做區目錄中運行 godoc。在執行下面的命令後,在瀏覽器中訪問 http://localhost:8000/pkg

$ godoc -http :8000

還可使用 -analysis=type 和 -analysis=pointer 命令行標誌參數,用於打開文檔和代碼中關於靜態分析的結果。

內部包

導入路徑中包含 internal 的狀況,會被特殊對待。這種包叫內部包,內部包只能被特定範圍內的包導入,就是以這個內部包的父目錄爲根的目錄樹中的其餘的包。

包的查詢

go list 工具上報可用包的信息。經過簡單的形式,go list 判斷一個包是否存在於工做區目錄中,若是存在就輸出它的導入路徑:

PS H:\Go\src\gopl\ch10> go list gopl/ch9/bank1
gopl/ch9/bank1

go list 命令的參數能夠包含 「...」 通配符(相似於通配符星號的做用),用來匹配包的導入路徑中的任意字符串。這能夠枚舉當前工做區目錄下的全部的包: go list ... ,輸出的結果實在太多了。
下面是一個指定的目錄中的全部的包:

PS H:\Go\src\gopl\ch10> go list gopl/ch9/...
gopl/ch9/bank1
gopl/ch9/bank2
gopl/ch9/bank3
gopl/ch9/hacker

下面則是查找某個主題:

PS H:\Go\src\gopl\ch10> go list ...netcat...
gopl/ch8/netcat1
gopl/ch8/netcat2
gopl/ch8/netcat3
gopl/exercise8/e8/netcat

這裏匹配的並非包名,而是包的整個導入路徑。這也包括從工做區目錄爲根開始的路徑所組成的字符串裏的任何內容。

go list 命令獲取每個包的完整元數據,而不只僅是導入路徑,而且提供各類對於用戶或者其餘工具可訪問的格式。

-json 標記使 go list 以 JSON 格式輸出每個包的完整記錄:

PS H:\Go\src\gopl\ch10> go list -json gopl/ch9/bank1
{
        "Dir": "H:\\Go\\src\\gopl\\ch9\\bank1",
        "ImportPath": "gopl/ch9/bank1",
        "Name": "bank",
        "Doc": "這是一個只有一個帳戶的併發安全銀行",
        "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"
        ]
}

這裏展開介紹其中三個字段的意義:

  1. GoFiles :庫源碼文件或命令源碼文件,就是實際保存產品代碼的文件列表
  2. TestGoFiles :測試源碼文件,都是以以 _test.go 結尾的文件,僅在編譯測試的時候纔會使用
  3. XTestGoFiles :外部測試包。也是測試源碼文件,也是 _test.go 結尾,也是在測試過程當中使用的。下篇的測試章節會講到

-f 標記可讓用戶經過 text/temple 包提供的模板語言來定製輸出的格式:

PS H:\Go\src\gopl\ch10> go list -json strconv
{
...
        "Deps": [
                "errors",
                "internal/cpu",
                "math",
                "math/bits",
                "unicode/utf8",
                "unsafe"
        ],
...
}

PS H:\Go\src\gopl\ch10> go list -f "{{join .Deps \"" \""}}" strconv
errors internal/cpu math math/bits unicode/utf8 unsafe
PS H:\Go\src\gopl\ch10> go list -f '{{join .Deps \" \"}}' strconv
errors internal/cpu math math/bits unicode/utf8 unsafe
PS H:\Go\src\gopl\ch10> go list -f "{{join .Deps `` ``}}" strconv
errors internal/cpu math math/bits unicode/utf8 unsafe
PS H:\Go\src\gopl\ch10> go list -f '{{join .Deps ` `}}' strconv
errors internal/cpu math math/bits unicode/utf8 unsafe

因爲這裏 -f 的參數中有空格,必需要用引號包起來。而參數的內容中還包含引號,因此這個參數很難寫。這裏只給出幾個示例,具體什麼規則講不清楚,大概有下面幾點:

  • 首先,這個windows的環境。Linux下沒有這麼坑
  • 雙引號內部的特殊符號,須要重複寫兩遍,兩個雙引號表示一個雙引號
  • 單引號內部的特殊符號,不用重複寫兩遍
  • 雙引號前面要轉義,因此在前面要加上斜槓(\)
  • 最後兩個命令,內層用的是撇號(`),因此不要加斜槓轉義

下面的命令輸出標準庫的 compress 子樹中每一個包的直接導入記錄:

PS H:\Go\src\gopl\ch10> go list compress/...
compress/bzip2
compress/flate
compress/gzip
compress/lzw
compress/zlib

PS H:\Go\src\gopl\ch10> 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 命令對於一次性的交互查詢和構建、測試腳本都很是有用。更多的參數信息,能夠經過 go help list 來獲取。

相關文章
相關標籤/搜索