update tw

This commit is contained in:
chai2010
2015-12-18 10:53:03 +08:00
parent 510c741a6f
commit c66a96ee52
106 changed files with 864 additions and 864 deletions

View File

@@ -1,11 +1,11 @@
## 10.1. 簡介
任何包繫統設計的目的都是了使大型程序的設計和維護, 通過將一組相關的特性放進一個獨立的單元以便於理解和更新, 時保持和程序中其他單元的相對獨立性. 這種模塊化的特性允許每個包可以被其他的不項目共享和重用, 在項目內甚至全球統一的分.
任何包繫統設計的目的都是了使大型程序的設計和維護, 通過將一組相關的特性放進一個獨立的單元以便於理解和更新, 時保持和程序中其他單元的相對獨立性. 這種模塊化的特性允許每個包可以被其他的不項目共享和重用, 在項目內甚至全球統一的分.
每個包定義了一個不的名稱空間用於它內部的每個標識符. 每個名稱關聯到一個特定的包, 我們最好給類型, 函數等選擇簡短清晰的名字, 這樣可以避免在我們使用它們的時候減少和其他部分名字的突.
每個包定義了一個不的名稱空間用於它內部的每個標識符. 每個名稱關聯到一個特定的包, 我們最好給類型, 函數等選擇簡短清晰的名字, 這樣可以避免在我們使用它們的時候減少和其他部分名字的突.
包還通過控製包內名字的可見性和是否導齣來實現封裝特性. 通過限製包成員的可見性隱藏包API的具體實現, 將允許包的維護者在不影響外部包用戶的前提下調整包的內部實現. 通過限製包內變量的可見性, 還可以控製用戶通過某些特定函數來訪問和更新內部變量, 這樣可以保內部變量的一緻性和併髮時的互斥約束.
包還通過控製包內名字的可見性和是否導齣來實現封裝特性. 通過限製包成員的可見性隱藏包API的具體實現, 將允許包的維護者在不影響外部包用戶的前提下調整包的內部實現. 通過限製包內變量的可見性, 還可以控製用戶通過某些特定函數來訪問和更新內部變量, 這樣可以保內部變量的一緻性和並發時的互斥約束.
當我們脩改了一個文件, 我們必鬚重新編譯改文件對應的包和所以依賴該包的其他包.卽使是從頭構建, Go的編譯器也明顯快於其他編譯語言. Go的編譯速度主要得益於三個特性. 第一點, 所有導入的包必鬚在每個文件的開頭顯式聲明, 這樣的話編譯器就沒有必要讀取分析整個文件來判斷包的依賴關繫. 第二點, 包的依賴關繫形成一個有無環圖, 因沒有循環依賴, 每個包可以被獨立編譯, 很可能是併髮編譯. 第三點, 編譯後包的目標文件不僅僅記包本身的導齣信息, 時還記了它的依賴關繫. 因此, 在編譯一個包的時候, 編譯器隻需要讀取每個直接導入包的目標文件, 而不是要遍所有依賴的的文件(譯註: 很多可能是間接依賴).
當我們脩改了一個文件, 我們必鬚重新編譯改文件對應的包和所以依賴該包的其他包.卽使是從頭構建, Go的編譯器也明顯快於其他編譯語言. Go的編譯速度主要得益於三個特性. 第一點, 所有導入的包必鬚在每個文件的開頭顯式聲明, 這樣的話編譯器就沒有必要讀取分析整個文件來判斷包的依賴關繫. 第二點, 包的依賴關繫形成一個有無環圖, 因沒有循環依賴, 每個包可以被獨立編譯, 很可能是並發編譯. 第三點, 編譯後包的目標文件不僅僅記包本身的導齣信息, 時還記了它的依賴關繫. 因此, 在編譯一個包的時候, 編譯器隻需要讀取每個直接導入包的目標文件, 而不是要遍所有依賴的的文件(譯註: 很多可能是間接依賴).

View File

@@ -15,6 +15,6 @@ import (
)
```
就像我們在2.6.1節提到過的, Go語言的規範沒有指明包導入路徑字符串的具體含義, 具體含義是由構建工具來解釋的. 在本章, 我們將深入討論Go工具箱的功能, 包括大傢經常使用的構建測試等功能. 當然, 也有第三方擴展的工具箱存在. 例如, Google公司內部的Go碼農, 就使用內部的多語言構建繫統, 用不的規則來處理名字和定位包, 指定單元測試等待, 這樣可以緊密適配他們內部的繫統.
就像我們在2.6.1節提到過的, Go語言的規範沒有指明包導入路徑字符串的具體含義, 具體含義是由構建工具來解釋的. 在本章, 我們將深入討論Go工具箱的功能, 包括大傢經常使用的構建測試等功能. 當然, 也有第三方擴展的工具箱存在. 例如, Google公司內部的Go碼農, 就使用內部的多語言構建繫統, 用不的規則來處理名字和定位包, 指定單元測試等待, 這樣可以緊密適配他們內部的繫統.
如果你計劃分享或佈包, 那導入路徑最好是全球唯一的. 了避免突, 所有非標準庫包的導入路徑建議以所在組織的互聯網域名前綴; 這樣也有利於包的檢索. 例如, 上的包導入聲明導入了Go團隊維護的HTML解析器和一個流行的第三方維護的MySQL驅動.
如果你計劃分享或佈包, 那導入路徑最好是全球唯一的. 了避免突, 所有非標準庫包的導入路徑建議以所在組織的互聯網域名前綴; 這樣也有利於包的檢索. 例如, 上的包導入聲明導入了Go團隊維護的HTML解析器和一個流行的第三方維護的MySQL驅動.

View File

@@ -1,6 +1,6 @@
## 10.3. 包聲明
在每個Go源文件的開頭都必鬚有包聲明. 主要的目的是確定當前包被其他包導入時默認的標識符(稱包名).
在每個Go源文件的開頭都必鬚有包聲明. 主要的目的是確定當前包被其他包導入時默認的標識符(稱包名).
例如, math/rand 包的每個文件的開頭都是 `package rand` 包聲明, 所有 當你導入這個包, 你可以用 rand.Int, rand.Float64 的方式訪問包的成員.
@@ -17,11 +17,11 @@ func main() {
}
```
通常來說, 默認的包名就是包導入路徑名的最後一段, 因此卽使兩個包的導入路徑不, 它們依然可能有一個相的包名. 例如, math/rand 和 crypto/rand 包的名字都是 rand. 稍後我們將看到如何時導入兩個包名字相的包.
通常來說, 默認的包名就是包導入路徑名的最後一段, 因此卽使兩個包的導入路徑不, 它們依然可能有一個相的包名. 例如, math/rand 和 crypto/rand 包的名字都是 rand. 稍後我們將看到如何時導入兩個包名字相的包.
關於默認包名一般採用導入路徑名的最後一段的約定有三種例外情況. 第一個例外是包對應一個可執行程序, 也就是 main 包, 這時候main包本身的導入路徑是無關緊要的. 這是給 go build (§10.7.3) 構建命令一個信息, 必鬚調用連接器生成一個可執行程序.
第二個例外是包所在的目中可能有一些文件名是以_test.go後綴的Go源文件(譯註: 前必鬚有其他的字符, 因 _ 前綴的源文件可能是被忽略的.), 且這些源文件聲明的包名也是以_test後綴名的. 這種目可以定義兩個包: 一個普通包, 加一個外部測試包. 以 _test 後綴包名的外部測試包由 go test 命令獨立編譯, 兩個包是相互獨立的. 外部測試包一般用來避免測試代碼中的導入包的循環導入依賴, 具體細節我們將在 11.2.4 中介紹.
第二個例外是包所在的目中可能有一些文件名是以_test.go後綴的Go源文件(譯註: 前必鬚有其他的字符, 因 _ 前綴的源文件可能是被忽略的.), 且這些源文件聲明的包名也是以_test後綴名的. 這種目可以定義兩個包: 一個普通包, 加一個外部測試包. 以 _test 後綴包名的外部測試包由 go test 命令獨立編譯, 兩個包是相互獨立的. 外部測試包一般用來避免測試代碼中的導入包的循環導入依賴, 具體細節我們將在 11.2.4 中介紹.
第三個例外是一些依賴版本號的管理工具會在導入路徑後追加版本號信息, 例如 "gopkg.in/yaml.v2". 這種情況下包的名字不包含版本號後綴, 隻是yaml.
第三個例外是一些依賴版本號的管理工具會在導入路徑後追加版本號信息, 例如 "gopkg.in/yaml.v2". 這種情況下包的名字不包含版本號後綴, 隻是yaml.

View File

@@ -1,6 +1,6 @@
## 10.4. 導入聲明
一個Go源文件可以在包聲明語句之後, 其他非導入聲明之前, 包含零到多個導入包聲明. 每個導入聲明可以單獨指定一個導入路徑, 通過圓括號包含指定多個導入路徑. 下兩個導入形式是等價的, 但是第二種形式更常見.
一個Go源文件可以在包聲明語句之後, 其他非導入聲明之前, 包含零到多個導入包聲明. 每個導入聲明可以單獨指定一個導入路徑, 通過圓括號包含指定多個導入路徑. 下兩個導入形式是等價的, 但是第二種形式更常見.
```Go
import "fmt"
@@ -12,7 +12,7 @@ import (
)
```
導入的包之間可以通過添加空行來分組; 通常將來自不組織的包獨自分組. 導入順序無關緊要, 但是一般會根據字符串順序排列. (gofmt和goimports的都可以將不分組的包獨立排序.)
導入的包之間可以通過添加空行來分組; 通常將來自不組織的包獨自分組. 導入順序無關緊要, 但是一般會根據字符串順序排列. (gofmt和goimports的都可以將不分組的包獨立排序.)
```Go
import (
@@ -25,7 +25,7 @@ import (
)
```
如果我們想時導入兩個名字相的包, 例如 math/rand 和 crypto/rand, 導入聲明必鬚至少一個名包指定一個新的包名, 以避免突. 這叫做導入包重命名.
如果我們想時導入兩個名字相的包, 例如 math/rand 和 crypto/rand, 導入聲明必鬚至少一個名包指定一個新的包名, 以避免突. 這叫做導入包重命名.
```Go
import (
@@ -34,8 +34,8 @@ import (
)
```
導入包重命名隻影響當前的Go源文件. 其他的Go源文件如果導入了相的包, 可以用導入包原本的名字或重命名另一個完全不的名字.
導入包重命名隻影響當前的Go源文件. 其他的Go源文件如果導入了相的包, 可以用導入包原本的名字或重命名另一個完全不的名字.
導入包重命名是一個有用的特性, 不僅僅是了解決名字突. 如果導入的一個包名很笨重, 特是在一些自動生成的代碼中, 這時候用一個簡短名稱會更方便. 選擇用簡短名稱重命名導入包時候最好統一, 比避免包名混亂. 選擇另一個包名稱還可以幫助避免和本地普通變量名產生突. 例如, 如果文件中已經有了一個名 path 的變量, 我們可以將"path"標準包重命名pathpkg.
導入包重命名是一個有用的特性, 不僅僅是了解決名字突. 如果導入的一個包名很笨重, 特是在一些自動生成的代碼中, 這時候用一個簡短名稱會更方便. 選擇用簡短名稱重命名導入包時候最好統一, 比避免包名混亂. 選擇另一個包名稱還可以幫助避免和本地普通變量名產生突. 例如, 如果文件中已經有了一個名 path 的變量, 我們可以將"path"標準包重命名pathpkg.
每個導入聲明明確指定了當前包和導入包之間的依賴關繫. 如果遇到包循環導入的情況, Go的構建工具將報告錯誤.

View File

@@ -1,14 +1,14 @@
## 10.5. 匿名導入
如果隻是導入一個包而不使用導入的包是一個編譯錯誤. 但是有時候我們隻是想利用導入包產生的副作用: 它會計算包級變量的初始化達式和執行導入包的 init 初始化函數 (§2.6.2). 這時候我們需要抑製“未使用的導入”錯誤是理的, 我們可以用下劃綫 `_` 來重命名導入的包. 像往常一樣, 下劃綫 `_` 空白標識符, 不能被訪問.
如果隻是導入一個包而不使用導入的包是一個編譯錯誤. 但是有時候我們隻是想利用導入包產生的副作用: 它會計算包級變量的初始化達式和執行導入包的 init 初始化函數 (§2.6.2). 這時候我們需要抑製“未使用的導入”錯誤是理的, 我們可以用下劃綫 `_` 來重命名導入的包. 像往常一樣, 下劃綫 `_` 空白標識符, 不能被訪問.
```Go
import _ "image/png" // register PNG decoder
```
這個被稱匿名導入. 它通常是用來實現一個編譯時機製, 然後通過在main主程序入口選擇性地導入附加的包. 首先, 讓我們看看如何使用它, 然後再看看它是如何工作的:
這個被稱匿名導入. 它通常是用來實現一個編譯時機製, 然後通過在main主程序入口選擇性地導入附加的包. 首先, 讓我們看看如何使用它, 然後再看看它是如何工作的:
標準庫的 image 圖像包導入了一個 `Decode` 函數, 用於從 `io.Reader` 接口讀取數據解碼圖像, 它調用底層註冊的圖像解碼器工作, 然後返迴 image.Image 類型的圖像. 使用 `image.Decode` 很容易編寫一個圖像格式的轉換工具, 讀取一種格式的圖像, 然後編碼另一種圖像格式:
標準庫的 image 圖像包導入了一個 `Decode` 函數, 用於從 `io.Reader` 接口讀取數據解碼圖像, 它調用底層註冊的圖像解碼器工作, 然後返迴 image.Image 類型的圖像. 使用 `image.Decode` 很容易編寫一個圖像格式的轉換工具, 讀取一種格式的圖像, 然後編碼另一種圖像格式:
```Go
gopl.io/ch10/jpeg
@@ -42,7 +42,7 @@ func toJPEG(in io.Reader, out io.Writer) error {
}
```
如果我們將 `gopl.io/ch3/mandelbrot` (§3.3) 的輸齣導入到這個工具的輸入, 它將解碼輸入的PNG格式圖像, 然後轉換JPEG格式的圖像(圖3.3).
如果我們將 `gopl.io/ch3/mandelbrot` (§3.3) 的輸齣導入到這個工具的輸入, 它將解碼輸入的PNG格式圖像, 然後轉換JPEG格式的圖像(圖3.3).
```
$ go build gopl.io/ch3/mandelbrot
@@ -51,7 +51,7 @@ $ ./mandelbrot | ./jpeg >mandelbrot.jpg
Input format = png
```
要註意 image/png 包的匿名導入語句. 如果沒有這一行語句, 依然可以編譯和運行, 但是它將不能識 PNG 格式的圖像:
要註意 image/png 包的匿名導入語句. 如果沒有這一行語句, 依然可以編譯和運行, 但是它將不能識 PNG 格式的圖像:
```
$ go build gopl.io/ch10/jpeg
@@ -59,7 +59,7 @@ $ ./mandelbrot | ./jpeg >mandelbrot.jpg
jpeg: image: unknown format
```
的代碼演示了它的工作機製. 標準庫提供了GIF, PNG, 和 JPEG 格式圖像的解碼器, 用戶也可以提供自己的解碼器, 但是了保存程序體積較小, 很多解碼器沒有被包含量, 除非是明確需要支持的格式. image.Decode 函數會査詢支持的格式列. 列的每個入口指定了四件事情: 格式的名稱; 一個用於描述這種圖像數據開頭部分模式的字符串, 用於解碼器檢測識; 一個 Decode 函數 用於解碼圖像; 一個 DecodeConfig 函數用於解碼圖像的大小和色空間的信息. 每個入口是通過調用 image.RegisterFormat 函數註冊, 一般是在每個格式包的初始化函數中調用, 例如 image/png 包是這樣的:
的代碼演示了它的工作機製. 標準庫提供了GIF, PNG, 和 JPEG 格式圖像的解碼器, 用戶也可以提供自己的解碼器, 但是了保存程序體積較小, 很多解碼器沒有被包含量, 除非是明確需要支持的格式. image.Decode 函數會査詢支持的格式列. 列的每個入口指定了四件事情: 格式的名稱; 一個用於描述這種圖像數據開頭部分模式的字符串, 用於解碼器檢測識; 一個 Decode 函數 用於解碼圖像; 一個 DecodeConfig 函數用於解碼圖像的大小和色空間的信息. 每個入口是通過調用 image.RegisterFormat 函數註冊, 一般是在每個格式包的初始化函數中調用, 例如 image/png 包是這樣的:
```Go
package png // image/png
@@ -75,7 +75,7 @@ func init() {
最終的效果是, 主程序值需要匿名導入需要 image.Decode 支持的格式對應解碼包就可以解碼圖像了.
數據庫包 database/sql 也是採用了類似的技, 讓用戶可以根據自己需要選擇導入必要的數據庫驅動. 例如:
數據庫包 database/sql 也是採用了類似的技, 讓用戶可以根據自己需要選擇導入必要的數據庫驅動. 例如:
```Go
import (
@@ -89,7 +89,7 @@ db, err = sql.Open("mysql", dbname) // OK
db, err = sql.Open("sqlite3", dbname) // returns error: unknown driver "sqlite3"
```
**練習 10.1:** 擴展 jpeg 程序, 支持任意圖像格式之間的相互轉換, 使用 image.Decode 檢測支持的格式類型, 然後步 flag 命令行標誌參數選擇輸齣的格式.
**練習 10.1:** 擴展 jpeg 程序, 支持任意圖像格式之間的相互轉換, 使用 image.Decode 檢測支持的格式類型, 然後步 flag 命令行標誌參數選擇輸齣的格式.
**練習 10.2:** 設計一個通用的壓縮文件讀取框架, 用來讀取 ZIP(archive/zip) 和 POSIX tar(archive/tar) 格式壓縮的文檔. 使用類似上的註冊機製來擴展支持不的壓縮格式, 然後根據需要通過匿名導入選擇支持的格式.
**練習 10.2:** 設計一個通用的壓縮文件讀取框架, 用來讀取 ZIP(archive/zip) 和 POSIX tar(archive/tar) 格式壓縮的文檔. 使用類似上的註冊機製來擴展支持不的壓縮格式, 然後根據需要通過匿名導入選擇支持的格式.

View File

@@ -6,14 +6,14 @@
當創建一個包, 一般要用短小的包名, 但也不能太短導緻難以理解.
標準庫中最常用的包有 bufio, bytes, flag, fmt, http, io, json, os, sort, sync, 和 time 等包.
它們的名字都簡潔明了. 例如, 不要將一個類似 imageutil 或 ioutilis 的通用包命名 util,
雖然它看起來很短小. 要量避免包名使用經常被用於侷部變量的名字, 這樣可能導緻用戶重命名導入包, 例如前看到的 path 包.
它們的名字都簡潔明了. 例如, 不要將一個類似 imageutil 或 ioutilis 的通用包命名 util,
雖然它看起來很短小. 要量避免包名使用經常被用於侷部變量的名字, 這樣可能導緻用戶重命名導入包, 例如前看到的 path 包.
包名時採用單數的形式. 標準庫的 bytes, errors, 和 strings 使用了復數是了避免和預定義的類型突, 樣還有 go/types 是了避免和關鍵字突.
包名時採用單數的形式. 標準庫的 bytes, errors, 和 strings 使用了復數是了避免和預定義的類型突, 樣還有 go/types 是了避免和關鍵字突.
要避免包名有其他的含義. 例如, 2.5節中我們的溫度轉換包最初使用了 temp 包名, 雖然沒有持續多久. 這是一個糟糕的做法, 因 `temp` 幾乎是臨時變量的義詞. 然後我們有一段時間使用了 temperature 作包名, 雖然名字沒有達包的眞是用途. 最後我們改成了 tempconv 包名, 和 strconv 類似也很簡潔明了.
要避免包名有其他的含義. 例如, 2.5節中我們的溫度轉換包最初使用了 temp 包名, 雖然沒有持續多久. 這是一個糟糕的做法, 因 `temp` 幾乎是臨時變量的義詞. 然後我們有一段時間使用了 temperature 作包名, 雖然名字沒有達包的眞是用途. 最後我們改成了 tempconv 包名, 和 strconv 類似也很簡潔明了.
現在讓我們看看如何命名包的襯衣. 由於是通過包的導入名字引入包裏麫的成員, 例如 fmt.Println, 時包含了包和成名的描述信息(翻譯障礙). 我們不需要關註Println的具體內容, 因 fmt 已經包含了這個信息. 當設計一個包的時候, 需要考慮包名和成員名兩個部分如何配. 下有一些例子:
現在讓我們看看如何命名包的襯衣. 由於是通過包的導入名字引入包裡面的成員, 例如 fmt.Println, 時包含了包和成名的描述信息(翻譯障礙). 我們不需要關註Println的具體內容, 因 fmt 已經包含了這個信息. 當設計一個包的時候, 需要考慮包名和成員名兩個部分如何配. 下有一些例子:
```
bytes.Equal flag.Int http.Get json.Marshal
@@ -33,7 +33,7 @@ type Reader struct{ /* ... */ }
func NewReader(s string) *Reader
```
string 本身沒有齣現在每個成員名字中. 因用戶會這樣引用這些成員 strings.Index, strings.Replacer 等.
string 本身沒有齣現在每個成員名字中. 因用戶會這樣引用這些成員 strings.Index, strings.Replacer 等.
其他一些包, 可能隻描述了單一的數據類型, 例如 html/template 和 math/rand 等, 隻暴露一個主要的數據結構和與它相關的方法, 還有一個 New 名字的函數用於創建實例.
@@ -44,11 +44,11 @@ type Rand struct{ /* ... */ }
func New(source Source) *Rand
```
這可能導緻一些名字重復, 例如 template.Template 或 rand.Rand, 這就是為什麼這些種類的包的名稱往往特短.
這可能導緻一些名字重復, 例如 template.Template 或 rand.Rand, 這就是爲什麽這些種類的包的名稱往往特短.
另一個極端, 還有像 net/http 包那樣含有非常多的名字和不多的數據類型, 因它們是要執行一個復雜的復任務. 管有將近二十種類型和更多的函數, 包中最重要的成員名字卻是簡單明了的: Get, Post, Handle, Error, Client, Server.
另一個極端, 還有像 net/http 包那樣含有非常多的名字和不多的數據類型, 因它們是要執行一個復雜的復任務. 管有將近二十種類型和更多的函數, 包中最重要的成員名字卻是簡單明了的: Get, Post, Handle, Error, Client, Server.
有包net/http這樣有很多名字沒有很多結構,因他們執行一個復雜任務。管二十類型和更多的功能,包最重要的成員最簡單的名字:Get、Post、處理、錯誤,客戶端,服務器。
有包net/http這樣有很多名字沒有很多結構,因他們執行一個復雜任務。管二十類型和更多的功能,包最重要的成員最簡單的名字:Get、Post、處理、錯誤,客戶端,服務器。

View File

@@ -1,14 +1,14 @@
### 10.7.1. 工作區結構
對於大多數的Go用戶, 隻需要配置一個名叫GOPATH的環境變量, 用來指定根工作目卽可. 當需要切換到不工作區的時候, 隻要更新GOPATH就可以了. 例如, 我們在編寫本書時, 將GOPATH設置 `$HOME/gobook`:
對於大多數的Go用戶, 隻需要配置一個名叫GOPATH的環境變量, 用來指定根工作目卽可. 當需要切換到不工作區的時候, 隻要更新GOPATH就可以了. 例如, 我們在編寫本書時, 將GOPATH設置 `$HOME/gobook`:
```
$ export GOPATH=$HOME/gobook
$ go get gopl.io/...
```
當你用前介紹的命令下載本書全部的程序之後, 你的當前工作區的目結構是這樣的:
當你用前介紹的命令下載本書全部的程序之後, 你的當前工作區的目結構是這樣的:
```
GOPATH/
@@ -35,9 +35,9 @@ GOPATH/
...
```
GOPATH對應的目有三個子目. 其中 src 子目用於存儲源代碼. 每個包保存在$GOPATH/src的相對路徑包導入路徑的子目中, 例如 gopl.io/ch1/helloworld 相對路徑. 我們看到, 一個GOPATH工作區的src目中可能有多個獨立的版本控製, 例如 gopl.io 或 golang.org. 其中 pkg 子目用於保存編譯後的包的目標文件, bin 子目用於保存編譯後的可執行程序, 例如 helloworld 程序.
GOPATH對應的目有三個子目. 其中 src 子目用於存儲源代碼. 每個包保存在$GOPATH/src的相對路徑包導入路徑的子目中, 例如 gopl.io/ch1/helloworld 相對路徑. 我們看到, 一個GOPATH工作區的src目中可能有多個獨立的版本控製, 例如 gopl.io 或 golang.org. 其中 pkg 子目用於保存編譯後的包的目標文件, bin 子目用於保存編譯後的可執行程序, 例如 helloworld 程序.
第二個環境變量 GOROOT 用來指定Go的安裝目, 還有它自帶的標準庫包的位置. GOROOT 的目結構和 GOPATH 類似, 因此存放 fmt 包的源代碼目彔為 $GOROOT/src/fmt. 用戶一般不需要設置 GOROOT, 默認情況下, Go工具會設置安裝的位置.
第二個環境變量 GOROOT 用來指定Go的安裝目, 還有它自帶的標準庫包的位置. GOROOT 的目結構和 GOPATH 類似, 因此存放 fmt 包的源代碼目録爲 $GOROOT/src/fmt. 用戶一般不需要設置 GOROOT, 默認情況下, Go工具會設置安裝的位置.
其中 `go env` 命令用於査看工具涉及的所有環境變量的值, 包括未設置環境變量的默認值. GOOS 用於指定目標操作繫統(例如 android, linux, darwin, 或 windows), GOARCH 用於指定處理器的類型, 例如 amd64, 386, 或 arm. 雖然 GOPATH 是唯一必需要設置的, 但是其它的也有偶爾用到.

View File

@@ -2,9 +2,9 @@
使用Go工具, 不僅可以根據包導入路徑找到本地工作區的包, 甚至可以從互聯網上找到和更新包.
使用命令 `go get` 可以下載一個單一的包或者用 `...` 下載整個子目彔裏麫的每個包. Go工具時計算下載所依賴的每個包, 這也是前一個例子中 golang.org/x/net/html 自動齣現在本地工作區目的原因.
使用命令 `go get` 可以下載一個單一的包或者用 `...` 下載整個子目録裡面的每個包. Go工具時計算下載所依賴的每個包, 這也是前一個例子中 golang.org/x/net/html 自動齣現在本地工作區目的原因.
一旦 `go get` 命令下載了包, 然後就是安裝包或包對應的命令. 我們將在下一節再關註它的細節, 現在隻是展示下整個過程是如何的簡單. 第一個命令是取 golint 工具, 用於檢測Go源代碼的編程風格是否有問題. 第二個命令是用 golint 對 2.6.2節的 gopl.io/ch2/popcount 包代碼進行編碼風格檢査. 它友好地報告了忘記了包的文檔:
一旦 `go get` 命令下載了包, 然後就是安裝包或包對應的命令. 我們將在下一節再關註它的細節, 現在隻是展示下整個過程是如何的簡單. 第一個命令是取 golint 工具, 用於檢測Go源代碼的編程風格是否有問題. 第二個命令是用 golint 對 2.6.2節的 gopl.io/ch2/popcount 包代碼進行編碼風格檢査. 它友好地報告了忘記了包的文檔:
```
$ go get github.com/golang/lint/golint
@@ -13,9 +13,9 @@ src/gopl.io/ch2/popcount/main.go:1:1:
package comment should be of the form "Package popcount ..."
```
`go get` 命令支持當前流行的託管網站 GitHub, Bitbucket, 和 Launchpad, 可以直接從它們的版本控製繫統請求代碼. 對於其他的網站, 你可能需要指定版本控製繫統的具體路徑和協議, 例如 Git 或 Mercurial. 運行 `go help importpath` 取更新的信息.
`go get` 命令支持當前流行的託管網站 GitHub, Bitbucket, 和 Launchpad, 可以直接從它們的版本控製繫統請求代碼. 對於其他的網站, 你可能需要指定版本控製繫統的具體路徑和協議, 例如 Git 或 Mercurial. 運行 `go help importpath` 取更新的信息.
`go get` 取的代碼是眞實的本地存儲倉庫, 不僅僅隻是復製文件, 因此你依然可以使用版本管理工具比較本地代碼的變更, 或者切換到其他的版本. 例如 golang.org/x/net 目對應一個 Git 倉庫:
`go get` 取的代碼是眞實的本地存儲倉庫, 不僅僅隻是復製文件, 因此你依然可以使用版本管理工具比較本地代碼的變更, 或者切換到其他的版本. 例如 golang.org/x/net 目對應一個 Git 倉庫:
```
$ cd $GOPATH/src/golang.org/x/net
@@ -24,7 +24,7 @@ origin https://go.googlesource.com/net (fetch)
origin https://go.googlesource.com/net (push)
```
需要註意的是導入路徑含有的網站域名和本地Git倉庫遠程的Git服務地址不相, 眞實的Git地址是 go.googlesource.com. 這其實是Go工具箱的一個特性, 可以讓包用一個自定義的導入路徑, 但是眞實的代碼卻是由更通用的服務提供, 例如 googlesource.com 或 github.com. 頁 https://golang.org/x/net/html 包含了如下的元數據, 告訴 Go 工具Git倉庫的眞實託管地址:
需要註意的是導入路徑含有的網站域名和本地Git倉庫遠程的Git服務地址不相, 眞實的Git地址是 go.googlesource.com. 這其實是Go工具箱的一個特性, 可以讓包用一個自定義的導入路徑, 但是眞實的代碼卻是由更通用的服務提供, 例如 googlesource.com 或 github.com. 頁 https://golang.org/x/net/html 包含了如下的元數據, 告訴 Go 工具Git倉庫的眞實託管地址:
```
$ go build gopl.io/ch1/fetch
@@ -33,9 +33,9 @@ $ ./fetch https://golang.org/x/net/html | grep go-import
content="golang.org/x/net git https://go.googlesource.com/net">
```
如果指定 `-u` 命令行標誌參數, `go get` 將確保所有的包和依賴的包的版本都是最新的, 然後編譯和安裝它們. 如果不包含該標誌參數, 如果包已經在本地存在, 那將不會被更新.
如果指定 `-u` 命令行標誌參數, `go get` 將確保所有的包和依賴的包的版本都是最新的, 然後編譯和安裝它們. 如果不包含該標誌參數, 如果包已經在本地存在, 那將不會被更新.
`go get -u` 命令隻是簡單地保每個包是最新版本, 如果你是第一次下載則比較很方便的; 但是如果是佈程序則可能是不適的, 因本地程序可能需要對依賴的包做精確的版本依賴管理. 通常的解決方案是使用 vendor 目存儲固定版本的代碼, 對本地依賴的包的版本更新也是謹慎和持續可控的. 在 Go 1.5 之前, 一般需要脩改包的導入路徑, 所以復製後 golang.org/x/net/html 導入路徑可能會變 gopl.io/vendor/golang.org/x/net/html. 最新的Go工具已經支持 vendor 特性, 但限於篇幅這裏併不討論細節. 不過可以通過 `go help gopath`査看 Vendor 目的幫助.
`go get -u` 命令隻是簡單地保每個包是最新版本, 如果你是第一次下載則比較很方便的; 但是如果是佈程序則可能是不適的, 因本地程序可能需要對依賴的包做精確的版本依賴管理. 通常的解決方案是使用 vendor 目存儲固定版本的代碼, 對本地依賴的包的版本更新也是謹慎和持續可控的. 在 Go 1.5 之前, 一般需要脩改包的導入路徑, 所以復製後 golang.org/x/net/html 導入路徑可能會變 gopl.io/vendor/golang.org/x/net/html. 最新的Go工具已經支持 vendor 特性, 但限於篇幅這裡並不討論細節. 不過可以通過 `go help gopath`査看 Vendor 目的幫助.
**練習 10.3:** 從 http://gopl.io/ch1/helloworld?go-get=1 取內容, 査看本書的代碼的眞實託管的網址(`go get`請求HTML頁時包含了 `go-get` 參數, 以區普通的瀏覽器請求.)
**練習 10.3:** 從 http://gopl.io/ch1/helloworld?go-get=1 取內容, 査看本書的代碼的眞實託管的網址(`go get`請求HTML頁時包含了 `go-get` 參數, 以區普通的瀏覽器請求.)

View File

@@ -1,11 +1,11 @@
### 10.7.3. 構建包
`go build` 命令編譯參數指定的每個包. 如果包是一個庫, 則忽略輸齣結果; 這可以用於檢測包的可以正確編譯的.
如果包的名字是 main, `go build` 將調用連接器在當前目創建一個可執行程序; 導入路徑的最後一段作可執行程序的名字.
如果包的名字是 main, `go build` 將調用連接器在當前目創建一個可執行程序; 導入路徑的最後一段作可執行程序的名字.
每個目隻包含一個包, 因此每個可執行程序後者叫Unix語中的命令, 會要求放到一個獨立的目. 這些目有時候會放在名叫 cmd 目的子目彔下麫, 例如用於提供Go文檔服務的 golang.org/x/tools/cmd/godoc 命令 (§10.7.4).
每個目隻包含一個包, 因此每個可執行程序後者叫Unix語中的命令, 會要求放到一個獨立的目. 這些目有時候會放在名叫 cmd 目的子目録下面, 例如用於提供Go文檔服務的 golang.org/x/tools/cmd/godoc 命令 (§10.7.4).
每個包可以由它們的導入路徑指定, 就像前看到的那樣, 或者有一個相對目的路徑知道, 必鬚以 `.``..` 開頭. 如果沒有指定參數, 那默認指定當前的目. 下的命令用於構建一個包, 雖然它們的寫法各不相:
每個包可以由它們的導入路徑指定, 就像前看到的那樣, 或者有一個相對目的路徑知道, 必鬚以 `.``..` 開頭. 如果沒有指定參數, 那默認指定當前的目. 下的命令用於構建一個包, 雖然它們的寫法各不相:
```
$ cd $GOPATH/src/gopl.io/ch1/helloworld
@@ -34,7 +34,7 @@ $ go build src/gopl.io/ch1/helloworld
Error: cannot find package "src/gopl.io/ch1/helloworld".
```
也可以指定包的源文件列, 一般這隻用於構建一些小程序或臨時性的實驗. 如果是main包, 將以第一個Go源文件的基礎文件名作可執行程序的名字.
也可以指定包的源文件列, 一般這隻用於構建一些小程序或臨時性的實驗. 如果是main包, 將以第一個Go源文件的基礎文件名作可執行程序的名字.
```
$ cat quoteargs.go
@@ -53,22 +53,22 @@ $ ./quoteargs one "two three" four\ five
["one" "two three" "four five"]
```
是對於這類一次性的程序, 我們繫統快的構建運行它. `go run` 命令結了構建和運行的兩個步驟:
是對於這類一次性的程序, 我們繫統快的構建運行它. `go run` 命令結了構建和運行的兩個步驟:
```
$ go run quoteargs.go one "two three" four\ five
["one" "two three" "four five"]
```
第一行的參數列中第一個不是以 .go 結尾的將作可執行程序的參數運行.
第一行的參數列中第一個不是以 .go 結尾的將作可執行程序的參數運行.
默認情況下, `go build` 命令構建指定的包和它依賴的包, 然後丟棄所有除了最後的可執行文件之外的中間編譯結果. 依賴分析和編譯都是很快的, 但是隨着項目增加到幾十個包和成韆上萬行代碼, 依賴關繫分析和編譯時間的消耗將變的可觀, 可能需要幾秒種, 卽使這些依賴項沒有改變.
`go install` 命令和 `go build` 命令很相似, 但是它保存每個包的編譯成果, 而不是將它們都丟棄. 被編譯的包被保存到 $GOPATH/pkg 目下和 src 目對應, 可執行程序被保存到 $GOPATH/bin 目. (很多用戶將 $GOPATH/bin 添加到可執行程序的蒐索列中.) 還有, `go install` 命令和 `go build` 命令都不會重新編譯沒有生變化的包, 這可以使後續構建更快捷. 了方便, `go build -i` 將安裝每個目標所依賴的包.
`go install` 命令和 `go build` 命令很相似, 但是它保存每個包的編譯成果, 而不是將它們都丟棄. 被編譯的包被保存到 $GOPATH/pkg 目下和 src 目對應, 可執行程序被保存到 $GOPATH/bin 目. (很多用戶將 $GOPATH/bin 添加到可執行程序的蒐索列中.) 還有, `go install` 命令和 `go build` 命令都不會重新編譯沒有生變化的包, 這可以使後續構建更快捷. 了方便, `go build -i` 將安裝每個目標所依賴的包.
編譯對應不的操作繫統平和CPU架構, `go install` 會將編譯結果安裝到 GOOS 和 GOARCH 對應的目. 例如, 在 Mac 繫統 golang.org/x/net/html 包將被安裝到 $GOPATH/pkg/darwin_amd64 目下的 golang.org/x/net/html.a 文件.
編譯對應不的操作繫統平和CPU架構, `go install` 會將編譯結果安裝到 GOOS 和 GOARCH 對應的目. 例如, 在 Mac 繫統 golang.org/x/net/html 包將被安裝到 $GOPATH/pkg/darwin_amd64 目下的 golang.org/x/net/html.a 文件.
鍼對不操作繫統或CPU的交叉構建也是很簡單的. 隻需要設置好目標對應的GOOS 和 GOARCH, 然後運行構建目卽可. 下交叉編譯的程序將輸齣它在編譯時操作繫統和CPU類型:
鍼對不操作繫統或CPU的交叉構建也是很簡單的. 隻需要設置好目標對應的GOOS 和 GOARCH, 然後運行構建目卽可. 下交叉編譯的程序將輸齣它在編譯時操作繫統和CPU類型:
```Go
gopl.io/ch10/cross
@@ -78,7 +78,7 @@ func main() {
}
```
以64位和32位環境分執行程序:
以64位和32位環境分執行程序:
```
$ go build gopl.io/ch10/cross
@@ -89,13 +89,13 @@ $ ./cross
darwin 386
```
有些包可能需要鍼對不衕平颱和處理器類型輸齣不版本的代碼, 以便於處理底層的可移植性問題或提供一些特點代碼提供優化. 如果一個文件名包含了一個操作繫統或處理器類型名字, 例如 net_linux.go 或 asm_amd64.s, Go工具將隻在對應的平編譯這些文件. 還有一個特的構建註釋註釋可以提供更多的構建控製. 例如, 文件中如果包含下的註釋:
有些包可能需要鍼對不同平檯和處理器類型輸齣不版本的代碼, 以便於處理底層的可移植性問題或提供一些特點代碼提供優化. 如果一個文件名包含了一個操作繫統或處理器類型名字, 例如 net_linux.go 或 asm_amd64.s, Go工具將隻在對應的平編譯這些文件. 還有一個特的構建註釋註釋可以提供更多的構建控製. 例如, 文件中如果包含下的註釋:
```Go
// +build linux darwin
```
在包聲明的前(含包的註釋), 告訴 `go build` 隻在鍼對 Linux 或 Mac OS X 是纔編譯這個文件. 下的構建註釋示不編譯這個文件:
在包聲明的前(含包的註釋), 告訴 `go build` 隻在鍼對 Linux 或 Mac OS X 是纔編譯這個文件. 下的構建註釋示不編譯這個文件:
```Go
// +build ignore

View File

@@ -1,8 +1,8 @@
### 10.7.4. 包文檔
Go的編碼風格鼓勵每個包提供良好的文檔. 包中每個導齣的成員和包聲明前都應該包含添加目的和用法說明的註釋.
Go的編碼風格鼓勵每個包提供良好的文檔. 包中每個導齣的成員和包聲明前都應該包含添加目的和用法說明的註釋.
Go中包文檔註釋一般是完整的句子, 第一行是包的摘要說明, 註釋後僅跟着包聲明語句. 函數的參數或其他的標識符不需要額外的引號或其他標記註明. 例如, 下是 fmt.Fprintf 的文檔註釋.
Go中包文檔註釋一般是完整的句子, 第一行是包的摘要說明, 註釋後僅跟着包聲明語句. 函數的參數或其他的標識符不需要額外的引號或其他標記註明. 例如, 下是 fmt.Fprintf 的文檔註釋.
```Go
// Fprintf formats according to a format specifier and writes to w.
@@ -10,13 +10,13 @@ Go中包文檔註釋一般是完整的句子, 第一行是包的摘要說明,
func Fprintf(w io.Writer, format string, a ...interface{}) (int, error)
```
Fprintf 函數格式化的細節在 fmt 包文檔中描述. 如果註釋後僅跟着包聲明語句, 那註釋對應整個包的文檔. 包文檔對應的註釋隻能有一個(譯註: 其實可以多個, 它們會組成一個包文檔註釋.), 可以齣現在任何一個源文件中. 如果包的註釋內容比較長, 可以當到一個獨立的文件中; fmt 包註釋就有 300 行之多. 這個專門用於保包文檔的文件通常叫 doc.go.
Fprintf 函數格式化的細節在 fmt 包文檔中描述. 如果註釋後僅跟着包聲明語句, 那註釋對應整個包的文檔. 包文檔對應的註釋隻能有一個(譯註: 其實可以多個, 它們會組成一個包文檔註釋.), 可以齣現在任何一個源文件中. 如果包的註釋內容比較長, 可以當到一個獨立的文件中; fmt 包註釋就有 300 行之多. 這個專門用於保包文檔的文件通常叫 doc.go.
好的文檔不需要麫麫俱到, 文檔本身應該是簡潔但可不忽略的. 事實上, Go的風格喜歡簡潔的文檔, 且文檔也是需要想代碼一樣維護的. 對於一組聲明語句, 可以一個精的句子描述, 如果是顯而易見的功能則不需要註釋.
好的文檔不需要面面俱到, 文檔本身應該是簡潔但可不忽略的. 事實上, Go的風格喜歡簡潔的文檔, 且文檔也是需要想代碼一樣維護的. 對於一組聲明語句, 可以一個精的句子描述, 如果是顯而易見的功能則不需要註釋.
在本書中, 隻要空間允許, 我們之前很多包聲明都包含了註釋文檔, 但你可以從標準庫中現很多更好的例子. 有兩個工具可以幫到你.
在本書中, 隻要空間允許, 我們之前很多包聲明都包含了註釋文檔, 但你可以從標準庫中現很多更好的例子. 有兩個工具可以幫到你.
`go doc` 命令打印包的聲明和每個成員的文檔註釋, 下是整個包的文檔:
`go doc` 命令打印包的聲明和每個成員的文檔註釋, 下是整個包的文檔:
```
$ go doc time
@@ -53,7 +53,7 @@ func (d Duration) Seconds() float64
Seconds returns the duration as a floating-point number of seconds.
```
該工具不需要輸入完整的包導入路徑或正確的大小寫. 下的命令打印 encoding/json 包的 (*json.Decoder).Decode 方法的文檔:
該工具不需要輸入完整的包導入路徑或正確的大小寫. 下的命令打印 encoding/json 包的 (*json.Decoder).Decode 方法的文檔:
```
$ go doc json.decode
@@ -63,11 +63,11 @@ func (dec *Decoder) Decode(v interface{}) error
it in the value pointed to by v.
```
第二個工具, 令人睏惑的也是名叫 godoc, 提供可以相互交叉引用的 HTML 頁, 但是包含和 `go doc`以及更多的信息. 10.1 節演示了 time 包的文檔, 11.6 節將看到godoc演示可以交互的示例程序. godoc 的在綫服務 https://godoc.org, 包含了成韆上萬的開源包的檢索工具.
第二個工具, 令人睏惑的也是名叫 godoc, 提供可以相互交叉引用的 HTML 頁, 但是包含和 `go doc`以及更多的信息. 10.1 節演示了 time 包的文檔, 11.6 節將看到godoc演示可以交互的示例程序. godoc 的在綫服務 https://godoc.org, 包含了成韆上萬的開源包的檢索工具.
You can also run an instance of godoc in your workspace if you want to browse your own packages. Visit http://localhost:8000/pkg in your browser while running this command:
你也可以在自己的工作區目允許 godoc 服務. 運行下的命令, 然後在瀏覽器査看 http://localhost:8000/pkg 頁:
你也可以在自己的工作區目允許 godoc 服務. 運行下的命令, 然後在瀏覽器査看 http://localhost:8000/pkg 頁:
```
$ godoc -http :8000

View File

@@ -1,12 +1,12 @@
### 10.7.5. 內部包
在Go程序中, 包的封裝機製是一個重要的特性. 導齣的標識符隻在一個包內部可以訪問, 導齣的標識符則是麫曏全世界可見.
在Go程序中, 包的封裝機製是一個重要的特性. 導齣的標識符隻在一個包內部可以訪問, 導齣的標識符則是面向全世界可見.
有時候, 一個中間的狀態可能也是有用的, 對於一小部分信任的包是可見的, 但不是對所有調用者都可見. 例如, 當我們計劃將一個大的包拆分很多小的更容易管理的子包, 但是我們不想將內部的子包結構也完全暴露齣去. 時, 我們肯呢個還希望在內部子包之間共享一些通用的處理包. 或者我們隻是想實驗一個新包的還不穩定的接口, 暫時隻暴露給一些受限製的客戶端.
有時候, 一個中間的狀態可能也是有用的, 對於一小部分信任的包是可見的, 但不是對所有調用者都可見. 例如, 當我們計劃將一個大的包拆分很多小的更容易管理的子包, 但是我們不想將內部的子包結構也完全暴露齣去. 時, 我們肯呢個還希望在內部子包之間共享一些通用的處理包. 或者我們隻是想實驗一個新包的還不穩定的接口, 暫時隻暴露給一些受限製的客戶端.
![](../images/ch10-01.png)
了滿足這些需求, Go構建工具支持包含 internal 名字的路徑段的包導入路徑. 這種包叫 internal 包, 一個 internal 包隻能被有和internal目彔有衕一個父目的包所導入. 例如, net/http/internal/chunked 內部包隻能被 net/http/httputil 或 net/http 導入, 但是不能被 net/url 包導入. 但是 net/url 包 可以導入 net/http/httputil.
了滿足這些需求, Go構建工具支持包含 internal 名字的路徑段的包導入路徑. 這種包叫 internal 包, 一個 internal 包隻能被有和internal目録有同一個父目的包所導入. 例如, net/http/internal/chunked 內部包隻能被 net/http/httputil 或 net/http 導入, 但是不能被 net/url 包導入. 但是 net/url 包 可以導入 net/http/httputil.
```
net/http

View File

@@ -1,13 +1,13 @@
### 10.7.6. 査詢包
`go list` 工具可以報告可用包的信息. 其最簡單的形式, 可以測試包是否在工作區打印他的導入路徑:
`go list` 工具可以報告可用包的信息. 其最簡單的形式, 可以測試包是否在工作區打印他的導入路徑:
```
$ go list github.com/go-sql-driver/mysql
github.com/go-sql-driver/mysql
```
`go list` 參數還可以用 `"..."` 示匹配任意的包的導入路徑. 我們可以用它來列工作區中的所有包:
`go list` 參數還可以用 `"..."` 示匹配任意的包的導入路徑. 我們可以用它來列工作區中的所有包:
```
$ go list ...
@@ -20,7 +20,7 @@ cmd/api
...many more...
```
或者是特定子目下的所有包:
或者是特定子目下的所有包:
```
$ go list gopl.io/ch3/...
@@ -41,7 +41,7 @@ encoding/xml
gopl.io/ch7/xmlselect
```
`go list` 可以取每個包完整的元信息, 而不僅僅隻是導入路徑, 這些信息可以以不格式提供給用戶. 其中 `-json` 標誌參數示用JSON格式打印每個包的元信息.
`go list` 可以取每個包完整的元信息, 而不僅僅隻是導入路徑, 這些信息可以以不格式提供給用戶. 其中 `-json` 標誌參數示用JSON格式打印每個包的元信息.
```
$ go list -json hash
@@ -71,7 +71,7 @@ $ go list -json hash
}
```
參數 `-f` 允許用戶使用 text/template (§4.6) 的模闆語言定義輸齣文本的格式. 下的命令打印 strconv 包的依賴的包, 然後用 join 模闆函數鏈接一行, 用一個空格分隔:
參數 `-f` 允許用戶使用 text/template (§4.6) 的模闆語言定義輸齣文本的格式. 下的命令打印 strconv 包的依賴的包, 然後用 join 模闆函數鏈接一行, 用一個空格分隔:
{% raw %}
```
@@ -80,7 +80,7 @@ errors math runtime unicode/utf8 unsafe
```
{% endraw %}
譯註: 上的命令在 Windows 的命令行運行會遇到 `template: main:1: unclosed action` 的錯誤. 產生錯誤的原因是因命令行對裏麫`" "` 參數進行轉義了. 按照下的方法解決轉義字符串的問題:
譯註: 上的命令在 Windows 的命令行運行會遇到 `template: main:1: unclosed action` 的錯誤. 產生錯誤的原因是因命令行對裡面`" "` 參數進行轉義了. 按照下的方法解決轉義字符串的問題:
{% raw %}
```
@@ -88,7 +88,7 @@ $ go list -f "{{join .Deps \" \"}}" strconv
```
{% endraw %}
的命令打印 compress 子目下所有包的依賴包列:
的命令打印 compress 子目下所有包的依賴包列:
{% raw %}
```
@@ -101,7 +101,7 @@ compress/zlib -> bufio compress/flate errors fmt hash hash/adler32 io
```
{% endraw %}
譯註: Windows 下樣有問題, 要避免轉義字符串的問題:
譯註: Windows 下樣有問題, 要避免轉義字符串的問題:
{% raw %}
```
@@ -113,7 +113,7 @@ go list 命令對於一次性的交互式査詢或自動化構建和測試腳本
在本章, 我們解釋了Go工具箱除了測試命令之外的所有重要的命令. 在下一章, 我們將看到如何用 `go test` 命令去測試Go程序.
**練習10.4:** 創建一個工具, 根據命令行指定的參數, 報告工作區所有依賴指定包的其他包集. 提示: 你需要運行 `go list` 命令兩次, 一次用於初始化包, 一次用於所有包. 你可能需要用 encoding/json (§4.5) 包來分析輸齣的 JSON 格式的信息.
**練習10.4:** 創建一個工具, 根據命令行指定的參數, 報告工作區所有依賴指定包的其他包集. 提示: 你需要運行 `go list` 命令兩次, 一次用於初始化包, 一次用於所有包. 你可能需要用 encoding/json (§4.5) 包來分析輸齣的 JSON 格式的信息.

View File

@@ -3,9 +3,9 @@
本章剩下的部分將討論Go工具箱的特性, 包括如何 下載, 格式化, 構建, 測試 和 安裝 Go 程序.
Go的工具箱集了一繫列的功能到一個命令集. 它可以看作是一個包管理器(類似於Linux中的apt和rpm工具), 用於包的査詢, 計算的包依賴關繫, 從遠程版本控製繫統和下載它們等任務. 它也是一個構建繫統, 計算文件的依賴關繫, 然後調用編譯器, 滙編器 和 連接器 構建程序, 雖然它故意被設計成沒有標準的make命令那復雜. 它也是一個測試驅動程序, 我們在第11章討論測試話題.
Go的工具箱集了一繫列的功能到一個命令集. 它可以看作是一個包管理器(類似於Linux中的apt和rpm工具), 用於包的査詢, 計算的包依賴關繫, 從遠程版本控製繫統和下載它們等任務. 它也是一個構建繫統, 計算文件的依賴關繫, 然後調用編譯器, 滙編器 和 連接器 構建程序, 雖然它故意被設計成沒有標準的make命令那復雜. 它也是一個測試驅動程序, 我們在第11章討論測試話題.
Go工具箱的命令有着類似"瑞士軍刀"的風格, 帶着一打子的子命令, 有一些我們經常用到, 例如 get, run, build, 和 fmt 等. 你可以運行 `go help` 命令査看內置的溫度, 了査詢方便, 我們列齣了最常用的命令:
Go工具箱的命令有着類似"瑞士軍刀"的風格, 帶着一打子的子命令, 有一些我們經常用到, 例如 get, run, build, 和 fmt 等. 你可以運行 `go help` 命令査看內置的溫度, 了査詢方便, 我們列齣了最常用的命令:
```
$ go
@@ -27,7 +27,7 @@ Use "go help [command]" for more information about a command.
...
```
了達到零配置的目標, Go的工具箱很多地方都依賴各種約定. 例如, 給定的源文件的名稱, Go工具可以找到對應的包, 因每個目隻包含了單一的包, 且到的導入路徑和工作區的目結構是對應的. 給定一個包的導入路徑, Go工具可以找到對應的目中保存對象的文件. 它還可以現存儲代碼倉庫的遠程服務器的URL.
了達到零配置的目標, Go的工具箱很多地方都依賴各種約定. 例如, 給定的源文件的名稱, Go工具可以找到對應的包, 因每個目隻包含了單一的包, 且到的導入路徑和工作區的目結構是對應的. 給定一個包的導入路徑, Go工具可以找到對應的目中保存對象的文件. 它還可以現存儲代碼倉庫的遠程服務器的URL.
{% include "./ch10-07-1.md" %}

View File

@@ -1,7 +1,7 @@
# 第十章 包和工具
現在隨便一個小程序的實現都可能包含超過10000個函數. 然後作者一般隻需要考慮其中很小的一部分和做很少的設計, 因為絶大部分代碼都是由他人編寫的, 它們通過類似包的方式被重用.
現在隨便一個小程序的實現都可能包含超過10000個函數. 然後作者一般隻需要考慮其中很小的一部分和做很少的設計, 因爲絕大部分代碼都是由他人編寫的, 它們通過類似包的方式被重用.
Go語言有超過100個的標準包, 大多數的程序提供了基礎構件. 在Go的社區, 有很多成熟的包被設計,共享,重用和改進, 目前已經佈了非常多的開源包, 它們可以通過 http://godoc.org 檢索. 在本章, 我們將演示如果使用已有的包和創建新的包.
Go語言有超過100個的標準包, 大多數的程序提供了基礎構件. 在Go的社區, 有很多成熟的包被設計,共享,重用和改進, 目前已經佈了非常多的開源包, 它們可以通過 http://godoc.org 檢索. 在本章, 我們將演示如果使用已有的包和創建新的包.
Go還自帶了工具箱, 裏麫有很多用來簡化工作區和包管理的小工具. 在本身開始的時候, 我們已經見識過如果使用工具箱自帶的工具來下載, 構件 和 運行我們的演示程序了. 在本章, 我們將看看這些工具的基本設計理論和試更多的功能, 例如打印工作區中包的文檔和査詢相關的元數據等. 在下一章, 我們將探討探索包的單元測試用法.
Go還自帶了工具箱, 裡面有很多用來簡化工作區和包管理的小工具. 在本身開始的時候, 我們已經見識過如果使用工具箱自帶的工具來下載, 構件 和 運行我們的演示程序了. 在本章, 我們將看看這些工具的基本設計理論和試更多的功能, 例如打印工作區中包的文檔和査詢相關的元數據等. 在下一章, 我們將探討探索包的單元測試用法.