ch2-06 review

This commit is contained in:
chai2010
2015-12-26 20:53:13 +08:00
parent e15e88dad7
commit 801a62f7a0
3 changed files with 42 additions and 36 deletions

View File

@@ -1,6 +1,6 @@
### 2.6.2. 包的初始化
包的初始化首先是解決包級變量的依賴順序, 然後安包級變量聲明出現的順序依次初始化:
包的初始化首先是解決包級變量的依賴順序然後安包級變量聲明出現的順序依次初始化
```Go
var a = b + c // a 第三個初始化, 爲 3
@@ -10,19 +10,19 @@ var c = 1 // c 第一個初始化, 爲 1
func f() int { return c + 1 }
```
如果包中含有多個 .go 文件, 它們按照發給編譯器的順序進行初始化, Go的構建工具首先將 .go 文件根據文件名排序, 然後依次調用編譯器編譯.
如果包中含有多個.go文件它們按照發給編譯器的順序進行初始化Go語言的構建工具首先將.go文件根據文件名排序然後依次調用編譯器編譯
對於在包級别聲明的變量, 如果有初始化表達式則用表達式初始化, 還有一些沒有初始化表達式的, 例如 某些表格數據 初始化併不是一個簡單的賦值過程. 在這種情況下, 我們可以用 init 初始化函數來簡化工作. 每個文件都可以包含多個 init 初始化函數
對於在包級别聲明的變量如果有初始化表達式則用表達式初始化還有一些沒有初始化表達式的例如某些表格數據初始化併不是一個簡單的賦值過程在這種情況下我們可以用一個特殊的init初始化函數來簡化初始化工作。每個文件都可以包含多個init初始化函數
```Go
func init() { /* ... */ }
```
這樣的init初始化函數除了不能被調用或引用外, 其他行爲和普通函數類似. 在每個文件中的init初始化函數, 在程序開始執行時按照它們聲明的順序被自動調用.
這樣的init初始化函數除了不能被調用或引用外其他行爲和普通函數類似在每個文件中的init初始化函數在程序開始執行時按照它們聲明的順序被自動調用
每個包在解決依賴的前提下, 以導入聲明的順序初始化, 每個包隻會被初始化一次. 因此, 如果一個 p 包導入了 q 包, 那麽在 p 包初始化的時候可以認爲 q 包已經初始化過了. 初始化工作是自下而上進行的, main 包最後被初始化. 以這種方式, 確保 在 main 函數執行之前, 所有的包都已經初始化了.
每個包在解決依賴的前提下以導入聲明的順序初始化每個包隻會被初始化一次。因此,如果一個p包導入了q包那麽在p包初始化的時候可以認爲q包必然已經初始化過了初始化工作是自下而上進行的main包最後被初始化以這種方式,可以確保在main函數執行之前,所有依然的包都已經完成初始化工作了。
下面的代碼定義了一個 PopCount 函數, 用於返迴一個數字中含二進製1bit的個數. 它使用 init 初始化函數來生成輔助表格 pc, pc 表格用於處理每個8bit寬度的數字含二進製的1bit的個數, 這樣的話在處理64bit寬度的數字時就沒有必要循環64次, 隻需要8次査表就可以了. (這併不是最快的統計1bit數目的算法, 但是可以方便演示init函數的用法, 併且演示了如果預生成輔助表格, 這是編程中常用的技術.)
下面的代碼定義了一個PopCount函數用於返迴一個數字中含二進製1bit的個數它使用init初始化函數來生成輔助表格pcpc表格用於處理每個8bit寬度的數字含二進製的1bit的bit個數這樣的話在處理64bit寬度的數字時就沒有必要循環64次隻需要8次査表就可以了。(這併不是最快的統計1bit數目的算法但是可以方便演示init函數的用法併且演示了如果預生成輔助表格這是編程中常用的技術)。
```Go
gopl.io/ch2/popcount
@@ -50,18 +50,28 @@ func PopCount(x uint64) int {
}
```
要註意的是 init 函數中, range 循環隻使用了索引, 省略了沒有用到的值部分.
循環也可以這樣寫:
譯註對於pc這類需要複雜處理的初始化可以通過將初始化邏輯包裝爲一個匿名函數處理像下面這樣
```Go
// pc[i] is the population count of i.
var pc [256]byte = func() (pc [256]byte) {
for i := range pc {
pc[i] = pc[i/2] + byte(i&1)
}
}()
```
要註意的是在init函數中range循環隻使用了索引省略了沒有用到的值部分。循環也可以這樣寫
```Go
for i, _ := range pc {
```
我們在下一節和10.5節還將看到其它使用init函數的地方.
我們在下一節和10.5節還將看到其它使用init函數的地方
**練習2.3:** 重寫 PopCount 函數, 用一個循環代替單一的表達式. 比較兩個版本的性能. (11.4節將展示如何繫統地比較兩個不同實現的性能.)
**練習 2.3** 重寫PopCount函數用一個循環代替單一的表達式比較兩個版本的性能。(11.4節將展示如何繫統地比較兩個不同實現的性能。)
**練習2.4:** 用移位算法重寫 PopCount 函數, 每次測試最右邊的1bit, 然後統計總數. 比較和査表算法的性能差異.
**練習 2.4** 用移位算法重寫PopCount函數每次測試最右邊的1bit然後統計總數比較和査表算法的性能差異
**練習2.5:** 表達式 `x&(x-1)` 用於將 x 的最低的一個1bit位清零. 使用這個格式重寫 PopCount 函數, 然後比較性能.
**練習 2.5** 表達式`x&(x-1)`用於將x的最低的一個非零的bit位清零使用這個算法重寫PopCount函數然後比較性能