Fixes #198
This commit is contained in:
chai2010
2016-01-18 11:22:04 +08:00
parent 884ada9cd0
commit 9666211cd7
71 changed files with 107 additions and 105 deletions

View File

@@ -1,6 +1,6 @@
## 2.1. 命名
Go語言中的函數名、變量名、常量名、類型名、語句標號和包名等所有的命名都遵循一個簡單的命名規則一個名字必以一個字母Unicode字母或下劃線開頭後面可以跟任意數量的字母、數字或下劃線。大寫字母和小寫字母是不同的heapSort和Heapsort是兩個不同的名字。
Go語言中的函數名、變量名、常量名、類型名、語句標號和包名等所有的命名都遵循一個簡單的命名規則一個名字必以一個字母Unicode字母或下劃線開頭後面可以跟任意數量的字母、數字或下劃線。大寫字母和小寫字母是不同的heapSort和Heapsort是兩個不同的名字。
Go語言中類似if和switch的關鍵字有25個關鍵字不能用於自定義名字隻能在特定語法結構中使用。
@@ -29,7 +29,7 @@ continue for import return var
這些內部預先定義的名字併不是關鍵字,你可以再定義中重新使用它們。在一些特殊的場景中重新定義它們也是有意義的,但是也要註意避免過度而引起語義混亂。
如果一個名字是在函數內部定義,那麽它的就隻在函數內部有效。如果是在函數外部定義,那麽將在當前包的所有文件中都可以訪問。名字的開頭字母的大小寫決定了名字在包外的可見性。如果一個名字是大寫字母開頭的(譯註:必是在函數外部定義的包級名字包級函數名本身也是包級名字那麽它將是導出的也就是説可以被外部的包訪問例如fmt包的Printf函數就是導出的可以在fmt包外部訪問。包本身的名字一般總是用小寫字母。
如果一個名字是在函數內部定義,那麽它的就隻在函數內部有效。如果是在函數外部定義,那麽將在當前包的所有文件中都可以訪問。名字的開頭字母的大小寫決定了名字在包外的可見性。如果一個名字是大寫字母開頭的(譯註:必是在函數外部定義的包級名字包級函數名本身也是包級名字那麽它將是導出的也就是説可以被外部的包訪問例如fmt包的Printf函數就是導出的可以在fmt包外部訪問。包本身的名字一般總是用小寫字母。
名字的長度沒有邏輯限製但是Go語言的風格是盡量使用短小的名字對於局部變量尤其是這樣你會經常看到i之類的短名字而不是冗長的theLoopIndex命名。通常來説如果一個名字的作用域比較大生命週期也比較長那麽用長的名字將會更有意義。

View File

@@ -2,7 +2,7 @@
聲明語句定義了程序的各種實體對象以及部分或全部的屬性。Go語言主要有四種類型的聲明語句var、const、type和func分别對應變量、常量、類型和函數實體對象的聲明。這一章我們重點討論變量和類型的聲明第三章將討論常量的聲明第五章將討論函數的聲明。
一個Go語言編寫的程序對應一個或多個以.go爲文件後綴名的源文件中。每個源文件以包的聲明語句開始説明該源文件是屬於哪個包。包聲明語句之後是import語句導入依賴的其它包然後是包一級的類型、變量、常量、函數的聲明語句包一級的各種類型的聲明語句的順序無關緊要譯註函數內部的名字則必先聲明之後才能使用)。例如,下面的例子中聲明了一個常量、一個函數和兩個變量:
一個Go語言編寫的程序對應一個或多個以.go爲文件後綴名的源文件中。每個源文件以包的聲明語句開始説明該源文件是屬於哪個包。包聲明語句之後是import語句導入依賴的其它包然後是包一級的類型、變量、常量、函數的聲明語句包一級的各種類型的聲明語句的順序無關緊要譯註函數內部的名字則必先聲明之後才能使用)。例如,下面的例子中聲明了一個常量、一個函數和兩個變量:
```Go
gopl.io/ch2/boiling

View File

@@ -53,7 +53,7 @@ in, err := os.Open(infile)
out, err := os.Create(outfile)
```
簡短變量聲明語句中必至少要聲明一個新的變量,下面的代碼將不能編譯通過:
簡短變量聲明語句中必至少要聲明一個新的變量,下面的代碼將不能編譯通過:
```Go
f, err := os.Open(infile)

View File

@@ -16,7 +16,7 @@ fmt.Println(x) // "2"
對於聚合類型每個成員——比如結構體的每個字段、或者是數組的每個元素——也都是對應一個變量,因此可以被取地址。
變量有時候被稱爲可尋址的值。卽使變量由表達式臨時生成,那麽表達式也必能接受`&`取地址操作。
變量有時候被稱爲可尋址的值。卽使變量由表達式臨時生成,那麽表達式也必能接受`&`取地址操作。
任何類型的指針的零值都是nil。如果`p != nil`測試爲眞那麽p是指向某個有效變量。指針之間也是可以進行相等測試的隻有當它們指向同一個變量或全部是nil時才相等。
@@ -55,7 +55,7 @@ incr(&v) // side effect: v is now 2
fmt.Println(incr(&v)) // "3" (and v is 3)
```
每次我們對一個變量取地址,或者複製指針,我們都是爲原變量創建了新的别名。例如,`*p`就是是 變量v的别名。指針特别有價值的地方在於我們可以不用名字而訪問一個變量但是這是一把雙刃劍要找到一個變量的所有訪問者併不容易我們必知道變量全部的别名譯註這是Go語言的垃圾迴收器所做的工作。不僅僅是指針會創建别名很多其他引用類型也會創建别名例如slice、map和chan甚至結構體、數組和接口都會創建所引用變量的别名。
每次我們對一個變量取地址,或者複製指針,我們都是爲原變量創建了新的别名。例如,`*p`就是是 變量v的别名。指針特别有價值的地方在於我們可以不用名字而訪問一個變量但是這是一把雙刃劍要找到一個變量的所有訪問者併不容易我們必知道變量全部的别名譯註這是Go語言的垃圾迴收器所做的工作。不僅僅是指針會創建别名很多其他引用類型也會創建别名例如slice、map和chan甚至結構體、數組和接口都會創建所引用變量的别名。
指針是實現標準庫中flag包的關鍵技術它使用命令行參數來設置對應變量的值而這些對應命令行標誌參數的變量可能會零散分布在整個程序中。爲了説明這一點在早些的echo版本中就包含了兩個可選的命令行參數`-n`用於忽略行尾的換行符,`-s sep`用於指定分隔字符默認是空格。下面這是第四個版本對應包路徑爲gopl.io/ch2/echo4。
@@ -82,9 +82,9 @@ func main() {
}
```
調用flag.Bool函數會創建一個新的對應布爾型標誌參數的變量。它有三個屬性第一個是的命令行標誌參數的名字“n”然後是該標誌參數的默認值這里是false最後是該標誌參數對應的描述信息。如果用戶在命令行輸入了一個無效的標誌參數或者輸入`-h``-help`參數那麽將打印所有標誌參數的名字、默認值和描述信息。類似的調用flag.String函數將於創建一個對應字符串類型的標誌參數變量同樣包含命令行標誌參數對應的參數名、默認值、和描述信息。程序中的`sep``n`變量分别是指向對應命令行標誌參數變量的指針,因此必`*sep``*n`形式的指針語法間接引用它們。
調用flag.Bool函數會創建一個新的對應布爾型標誌參數的變量。它有三個屬性第一個是的命令行標誌參數的名字“n”然後是該標誌參數的默認值這里是false最後是該標誌參數對應的描述信息。如果用戶在命令行輸入了一個無效的標誌參數或者輸入`-h``-help`參數那麽將打印所有標誌參數的名字、默認值和描述信息。類似的調用flag.String函數將於創建一個對應字符串類型的標誌參數變量同樣包含命令行標誌參數對應的參數名、默認值、和描述信息。程序中的`sep``n`變量分别是指向對應命令行標誌參數變量的指針,因此必`*sep``*n`形式的指針語法間接引用它們。
當程序運行時,必在使用標誌參數對應的變量之前調用先flag.Parse函數用於更新每個標誌參數對應變量的值之前是默認值。對於非標誌參數的普通命令行參數可以通過調用flag.Args()函數來訪問返迴值對應對應一個字符串類型的slice。如果在flag.Parse函數解析命令行參數時遇到錯誤默認將打印相關的提示信息然後調用os.Exit(2)終止程序。
當程序運行時,必在使用標誌參數對應的變量之前調用先flag.Parse函數用於更新每個標誌參數對應變量的值之前是默認值。對於非標誌參數的普通命令行參數可以通過調用flag.Args()函數來訪問返迴值對應對應一個字符串類型的slice。如果在flag.Parse函數解析命令行參數時遇到錯誤默認將打印相關的提示信息然後調用os.Exit(2)終止程序。
讓我們運行一些echo測試用例

View File

@@ -9,7 +9,7 @@ fmt.Println(*p) // "0"
fmt.Println(*p) // "2"
```
用new創建變量和普通變量聲明語句方式創建變量沒有什麽區别除了不需要聲明一個臨時變量的名字外我們還可以在表達式中使用new(T)。換言之new函數類似是一種語法,而不是一個新的基礎概念。
用new創建變量和普通變量聲明語句方式創建變量沒有什麽區别除了不需要聲明一個臨時變量的名字外我們還可以在表達式中使用new(T)。換言之new函數類似是一種語法,而不是一個新的基礎概念。
下面的兩個newInt函數有着相同的行爲

View File

@@ -44,7 +44,7 @@ func f() { func g() {
}
```
這里的x變量必在堆上分配因爲它在函數退出後依然可以通過包一級的global變量找到雖然它是在函數內部定義的用Go語言的術語説這個x局部變量從函數f中逃逸了。相反當g函數返迴時變量`*y`將是不可達的,也就是説可以馬上被迴收的。因此,`*y`併沒有從函數g中逃逸編譯器可以選擇在棧上分配`*y`的存儲空間譯註也可以選擇在堆上分配然後由Go語言的GC迴收這個變量的內存空間雖然這里用的是new方式。其實在任何時候你併不需爲了編寫正確的代碼而要考慮變量的逃逸行爲要記住的是逃逸的變量需要額外分配內存同時對性能的優化可能會産生細微的影響。
這里的x變量必在堆上分配因爲它在函數退出後依然可以通過包一級的global變量找到雖然它是在函數內部定義的用Go語言的術語説這個x局部變量從函數f中逃逸了。相反當g函數返迴時變量`*y`將是不可達的,也就是説可以馬上被迴收的。因此,`*y`併沒有從函數g中逃逸編譯器可以選擇在棧上分配`*y`的存儲空間譯註也可以選擇在堆上分配然後由Go語言的GC迴收這個變量的內存空間雖然這里用的是new方式。其實在任何時候你併不需爲了編寫正確的代碼而要考慮變量的逃逸行爲要記住的是逃逸的變量需要額外分配內存同時對性能的優化可能會産生細微的影響。
Go語言的自動垃圾收集器對編寫正確的代碼是一個鉅大的幫助但也併不是説你完全不用考慮內存了。你雖然不需要顯式地分配和釋放內存但是要編寫高效的程序你依然需要了解變量的生命週期。例如如果將指向短生命週期對象的指針保存到具有長生命週期的對象中特别是保存到全局變量時會阻止對短生命週期對象的垃圾迴收從而可能影響程序的性能

View File

@@ -39,7 +39,7 @@ i, j, k = 2, 3, 5
但如果表達式太複雜的話,應該盡量避免過度使用元組賦值;因爲每個變量單獨賦值語句的寫法可讀性會更好。
有些表達式會産生多個值,比如調用一個有多個返迴值的函數。當這樣一個函數調用出現在元組賦值右邊的表達式中時(譯註:右邊不能再有其它表達式),左邊變量的數目必和右邊一致。
有些表達式會産生多個值,比如調用一個有多個返迴值的函數。當這樣一個函數調用出現在元組賦值右邊的表達式中時(譯註:右邊不能再有其它表達式),左邊變量的數目必和右邊一致。
```Go
f, err = os.Open("foo.txt") // function call returns two values

View File

@@ -16,10 +16,10 @@ medals[2] = "bronze"
map和chan的元素雖然不是普通的變量但是也有類似的隱式賦值行爲。
不管是隱式還是顯式地賦值,在賦值語句左邊的變量和右邊最終的求到的值必有相同的數據類型。更直白地説,隻有右邊的值對於左邊的變量是可賦值的,賦值語句才是允許的。
不管是隱式還是顯式地賦值,在賦值語句左邊的變量和右邊最終的求到的值必有相同的數據類型。更直白地説,隻有右邊的值對於左邊的變量是可賦值的,賦值語句才是允許的。
可賦值性的規則對於不同類型有着不同要求,對每個新類型特殊的地方我們會專門解釋。對於目前我們已經討論過的類型,它的規則是簡單的:類型必完全匹配nil可以賦值給任何指針或引用類型的變量。常量§3.6)則有更靈活的賦值規則,因爲這樣可以避免不必要的顯式的類型轉換。
可賦值性的規則對於不同類型有着不同要求,對每個新類型特殊的地方我們會專門解釋。對於目前我們已經討論過的類型,它的規則是簡單的:類型必完全匹配nil可以賦值給任何指針或引用類型的變量。常量§3.6)則有更靈活的賦值規則,因爲這樣可以避免不必要的顯式的類型轉換。
對於兩個值是否可以用`==``!=`進行相等比較的能力也和可賦值能力有關繫:對於任何類型的值的相等比較,第二個值必是對第一個值類型對應的變量是可賦值的,反之依然。和前面一樣,我們會對每個新類型比較特殊的地方做專門的解釋。
對於兩個值是否可以用`==``!=`進行相等比較的能力也和可賦值能力有關繫:對於任何類型的值的相等比較,第二個值必是對第一個值類型對應的變量是可賦值的,反之依然。和前面一樣,我們會對每個新類型比較特殊的地方做專門的解釋。

View File

@@ -2,7 +2,7 @@
Go語言中的包和其他語言的庫或模塊的概念類似目的都是爲了支持模塊化、封裝、單獨編譯和代碼重用。一個包的源代碼保存在一個或多個以.go爲文件後綴名的源文件中通常一個包所在目録路徑的後綴是包的導入路徑例如包gopl.io/ch1/helloworld對應的目録路徑是$GOPATH/src/gopl.io/ch1/helloworld。
每個包都對應一個獨立的名字空間。例如在image包中的Decode函數和在unicode/utf16包中的 Decode函數是不同的。要在外部引用該函數顯式使用image.Decode或utf16.Decode形式訪問。
每個包都對應一個獨立的名字空間。例如在image包中的Decode函數和在unicode/utf16包中的 Decode函數是不同的。要在外部引用該函數顯式使用image.Decode或utf16.Decode形式訪問。
包還可以讓我們通過控製哪些名字是外部可見的來隱藏內部實現信息。在Go語言中一個簡單的規則是如果一個名字是大寫字母開頭的那麽該名字是導出的譯註因爲漢字不區分大小寫因此漢字開頭的名字是沒有導出的