diff --git a/SUMMARY-github.md b/SUMMARY-github.md index e9a39e2..39d7d8c 100644 --- a/SUMMARY-github.md +++ b/SUMMARY-github.md @@ -129,7 +129,7 @@ * [10.2. 導入路徑](ch10/ch10-02.md) * [10.3. 包聲明](ch10/ch10-03.md) * [10.4. 導入聲明](ch10/ch10-04.md) - * [10.5. 匿名導入](ch10/ch10-05.md) + * [10.5. 包的匿名導入](ch10/ch10-05.md) * [10.6. 包和命名](ch10/ch10-06.md) * [10.7. 工具](ch10/ch10-07.md) * [10.7.1. 工作區結構](ch10/ch10-07-1.md) diff --git a/SUMMARY.md b/SUMMARY.md index 813f51e..aeba4ea 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -96,7 +96,7 @@ * [導入路徑](ch10/ch10-02.md) * [包聲明](ch10/ch10-03.md) * [導入聲明](ch10/ch10-04.md) - * [匿名導入](ch10/ch10-05.md) + * [包的匿名導入](ch10/ch10-05.md) * [包和命名](ch10/ch10-06.md) * [工具](ch10/ch10-07.md) * [測試](ch11/ch11.md) diff --git a/ch10/ch10-05.md b/ch10/ch10-05.md index db5dca5..141eb69 100644 --- a/ch10/ch10-05.md +++ b/ch10/ch10-05.md @@ -1,14 +1,14 @@ -## 10.5. 匿名導入 +## 10.5. 包的匿名導入 -如果隻是導入一個包而併不使用導入的包是一個編譯錯誤. 但是有時候我們隻是想利用導入包産生的副作用: 它會計算包級變量的初始化表達式和執行導入包的 init 初始化函數 (§2.6.2). 這時候我們需要抑製“未使用的導入”錯誤是合理的, 我們可以用下劃線 `_` 來重命名導入的包. 像往常一樣, 下劃線 `_` 爲空白標識符, 併不能被訪問. +如果隻是導入一個包而併不使用導入的包將會導致一個編譯錯誤。但是有時候我們隻是想利用導入包而産生的副作用:它會計算包級變量的初始化表達式和執行導入包的init初始化函數(§2.6.2)。這時候我們需要抑製“unused import”編譯錯誤,我們可以用下劃線`_`來重命名導入的包。像往常一樣,下劃線`_`爲空白標識符,併不能被訪問。 ```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函數註冊,一般是在每個格式包的init初始化函數中調用,例如image/png包是這樣註冊的: ```Go package png // image/png @@ -73,9 +73,9 @@ func init() { } ``` -最終的效果是, 主程序值需要匿名導入需要 image.Decode 支持的格式對應解碼包就可以解碼圖像了. +最終的效果是,主程序隻需要匿名導入特定圖像驅動包就可以用image.Decode解碼對應格式的圖像了。 -數據庫包 database/sql 也是采用了類似的技術, 讓用戶可以根據自己需要選擇導入必要的數據庫驅動. 例如: +數據庫包database/sql也是采用了類似的技術,讓用戶可以根據自己需要選擇導入必要的數據庫驅動。例如: ```Go import ( @@ -89,7 +89,6 @@ 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.2:** 設計一個通用的壓縮文件讀取框架, 用來讀取 ZIP(archive/zip) 和 POSIX tar(archive/tar) 格式壓縮的文檔. 使用類似上面的註冊機製來擴展支持不同的壓縮格式, 然後根據需要通過匿名導入選擇支持的格式. +**練習 10.1:** 擴展jpeg程序,以支持任意圖像格式之間的相互轉換,使用image.Decode檢測支持的格式類型,然後通過flag命令行標誌參數選擇輸出的格式。 +**練習 10.2:** 設計一個通用的壓縮文件讀取框架,用來讀取ZIP(archive/zip)和POSIX tar(archive/tar)格式壓縮的文檔。使用類似上面的註冊技術來擴展支持不同的壓縮格式,然後根據需要通過匿名導入選擇導入要支持的壓縮格式的驅動包。