mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-10-18 21:11:43 +00:00
回到简体
This commit is contained in:
@@ -1,28 +1,28 @@
|
||||
### 2.6.2. 包的初始化
|
||||
|
||||
包的初始化首先是解決包級變量的依賴順序,然後安照包級變量聲明出現的順序依次初始化:
|
||||
包的初始化首先是解决包级变量的依赖顺序,然后安照包级变量声明出现的顺序依次初始化:
|
||||
|
||||
```Go
|
||||
var a = b + c // a 第三個初始化, 爲 3
|
||||
var b = f() // b 第二個初始化, 爲 2, 通過調用 f (依賴c)
|
||||
var c = 1 // c 第一個初始化, 爲 1
|
||||
var a = b + c // a 第三个初始化, 为 3
|
||||
var b = f() // b 第二个初始化, 为 2, 通过调用 f (依赖c)
|
||||
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的bit個數,這樣的話在處理64bit寬度的數字時就沒有必要循環64次,隻需要8次査表就可以了。(這併不是最快的統計1bit數目的算法,但是它可以方便演示init函數的用法,併且演示了如果預生成輔助表格,這是編程中常用的技術)。
|
||||
下面的代码定义了一个PopCount函数,用于返回一个数字中含二进制1bit的个数。它使用init初始化函数来生成辅助表格pc,pc表格用于处理每个8bit宽度的数字含二进制的1bit的bit个数,这样的话在处理64bit宽度的数字时就没有必要循环64次,只需要8次查表就可以了。(这并不是最快的统计1bit数目的算法,但是它可以方便演示init函数的用法,并且演示了如果预生成辅助表格,这是编程中常用的技术)。
|
||||
|
||||
<u><i>gopl.io/ch2/popcount</i></u>
|
||||
```Go
|
||||
@@ -50,7 +50,7 @@ func PopCount(x uint64) int {
|
||||
}
|
||||
```
|
||||
|
||||
譯註:對於pc這類需要複雜處理的初始化,可以通過將初始化邏輯包裝爲一個匿名函數處理,像下面這樣:
|
||||
译注:对于pc这类需要复杂处理的初始化,可以通过将初始化逻辑包装为一个匿名函数处理,像下面这样:
|
||||
|
||||
```Go
|
||||
// pc[i] is the population count of i.
|
||||
@@ -62,16 +62,16 @@ var pc [256]byte = func() (pc [256]byte) {
|
||||
}()
|
||||
```
|
||||
|
||||
要註意的是在init函數中,range循環隻使用了索引,省略了沒有用到的值部分。循環也可以這樣寫:
|
||||
要注意的是在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的最低的一個非零的bit位清零。使用這個算法重寫PopCount函數,然後比較性能。
|
||||
**练习 2.5:** 表达式`x&(x-1)`用于将x的最低的一个非零的bit位清零。使用这个算法重写PopCount函数,然后比较性能。
|
||||
|
Reference in New Issue
Block a user