ch2-04 review

This commit is contained in:
chai2010 2015-12-26 16:57:06 +08:00
parent a44fb5ee9e
commit fa63a48058
3 changed files with 34 additions and 26 deletions

View File

@ -1,6 +1,6 @@
### 2.4.1. 元組賦值 ### 2.4.1. 元組賦值
元組賦值是另一種形式的賦值語句, 允許同時更新多個變量的值. 在賦值之前, 賦值語句右邊的所有表達式將會先進行求值, 然後再統一更新左邊變量的值. 這對於處理有些同時齣現在元組賦值語句左右兩邊的變量很有幫助, 例如我們可以這樣交換兩個變量的值: 元組賦值是另一種形式的賦值語句,它允許同時更新多個變量的值。在賦值之前,賦值語句右邊的所有表達式將會先進行求值,然後再統一更新左邊對應變量的值。這對於處理有些同時齣現在元組賦值語句左右兩邊的變量很有幫助,例如我們可以這樣交換兩個變量的值:
```Go ```Go
x, y = y, x x, y = y, x
@ -8,7 +8,7 @@ x, y = y, x
a[i], a[j] = a[j], a[i] a[i], a[j] = a[j], a[i]
``` ```
或者是計算兩個整數值的的最大公約數(GCD): 或者是計算兩個整數值的的最大公約數GCD譯註GCD不是那個敏感字而是greatest common divisor的縮寫歐幾里德的GCD是最早的非平凡算法
```Go ```Go
func gcd(x, y int) int { func gcd(x, y int) int {
@ -19,7 +19,7 @@ func gcd(x, y int) int {
} }
``` ```
或者是計算斐波納契數列(Fibonacci)的第N個數: 或者是計算斐波納契數列Fibonacci的第N個數
```Go ```Go
func fib(n int) int { func fib(n int) int {
@ -31,22 +31,21 @@ func fib(n int) int {
} }
``` ```
元組賦值也可以使一繫列瑣碎賦值更緊湊(譯註: 特别是在for循環的初始化部分), 元組賦值也可以使一繫列瑣碎賦值更加緊湊(譯註: 特别是在for循環的初始化部分
```Go ```Go
i, j, k = 2, 3, 5 i, j, k = 2, 3, 5
``` ```
但如果表達式太複雜的話, 應該盡量避免元組賦值; 因爲一個個單獨的賦值語句的可讀性會更好. 但如果表達式太複雜的話,應該盡量避免過度使用元組賦值;因爲每個變量單獨賦值語句的寫法可讀性會更好。
某些表達式會産生多個值, 比如調用一個有多個返迴值的函數. 有些表達式會産生多個值,比如調用一個有多個返迴值的函數。當這樣一個函數調用齣現在元組賦值右邊的表達式中時(譯註:右邊不能再有其它表達式),左邊變量的數目必鬚和右邊一致。
當這樣一個函數調用齣現在元組賦值右邊的表達式中時(譯註: 右邊不能再有其他表達式), 左邊變量的數目必鬚和右邊一致.
```Go ```Go
f, err = os.Open("foo.txt") // function call returns two values f, err = os.Open("foo.txt") // function call returns two values
``` ```
通常, 這類函數會用額外的返迴值表達某種錯誤類型, 例如 os.Open 是返迴一個 error 類型的錯誤, 還有一些是返迴布爾值, 通常被稱爲ok. 在稍後我們看到的三個操作都是類似的行爲. 如果 字典査找(§4.3), 類型斷言(§7.10), 或 通道接收(§8.4.2) 齣現在賦值語句的右邊, 它們都將産生兩個結果, 有一個額外的布爾結果表示操作是否成功: 通常這類函數會用額外的返迴值來表達某種錯誤類型例如os.Open是用額外的返迴值返迴一個error類型的錯誤還有一些是用來返迴布爾值通常被稱爲ok。在稍後我們將看到的三個操作都是類似的用法。如果map査找§4.3、類型斷言§7.10或通道接收§8.4.2)齣現在賦值語句的右邊,它們都可能會産生兩個結果,有一個額外的布爾結果表示操作是否成功:
```Go ```Go
v, ok = m[key] // map lookup v, ok = m[key] // map lookup
@ -54,10 +53,22 @@ v, ok = x.(T) // type assertion
v, ok = <-ch // channel receive v, ok = <-ch // channel receive
``` ```
和變量的聲明一樣, 我們可以用下劃線空白標識符 `_` 來丟棄不需要的值. 譯註map査找§4.3、類型斷言§7.10或通道接收§8.4.2齣現在賦值語句的右邊時併不一定是産生兩個結果也可能隻産生一個結果。對於值産生一個結果的情形map査找失敗時會返迴零值類型斷言失敗時會發送運行時panic異常通道接收失敗時會返迴零值阻塞不算是失敗。例如下面的例子
```Go
v = m[key] // map査找失敗時返迴零值
v = x.(T) // type斷言失敗時panic異常
v = <-ch // 管道接收失敗時返迴零值阻塞不算是失敗
_, ok = m[key] // map返迴2個值
_, ok = mm[""], false // map返迴1個值
_ = mm[""] // map返迴1個值
```
和變量聲明一樣,我們可以用下劃線空白標識符`_`來丟棄不需要的值。
```Go ```Go
_, err = io.Copy(dst, src) // 丟棄字節數 _, err = io.Copy(dst, src) // 丟棄字節數
_, ok = x.(T) // 隻檢測類型, 忽略具體值 _, ok = x.(T) // 隻檢測類型忽略具體值
``` ```

View File

@ -1,12 +1,12 @@
### 2.4.2. 可賦值性 ### 2.4.2. 可賦值性
賦值語句是顯示的賦值形式, 但是程序中還有很多地方會發送隱式的賦值行爲: 函數調用將隱式地將調用參數的值賦值給函數的參數變量, 一個返迴語句將隱式地將返迴操作的值賦值給結果變量, 一個複合類型的字面量(§4.2)也會産生賦值行爲. 例如下面的語句: 賦值語句是顯式的賦值形式但是程序中還有很多地方會發生隱式的賦值行爲函數調用會隱式地將調用參數的值賦值給函數的參數變量一個返迴語句將隱式地將返迴操作的值賦值給結果變量一個複合類型的字面量§4.2)也會産生賦值行爲。例如下面的語句:
```Go ```Go
medals := []string{"gold", "silver", "bronze"} medals := []string{"gold", "silver", "bronze"}
``` ```
隱式地對切片的每個元素進行賦值操作, 類似這樣寫的行爲: 隱式地對slice的每個元素進行賦值操作類似這樣寫的行爲
```Go ```Go
medals[0] = "gold" medals[0] = "gold"
@ -14,15 +14,12 @@ medals[1] = "silver"
medals[2] = "bronze" medals[2] = "bronze"
``` ```
字典和管道的元素, 雖然不是普通的變量, 但是也有類似的隱式賦值行爲. map和chan的元素雖然不是普通的變量但是也有類似的隱式賦值行爲。
不管是隱式還是顯示地賦值, 在賦值語句坐標的變量和右邊最終的求到的值必鬚有相同的數據類型. 更直白地説, 隻有右邊的值對於左邊的變量是可賦值的, 賦值語句纔是允許的. 不管是隱式還是顯式地賦值,在賦值語句左邊的變量和右邊最終的求到的值必鬚有相同的數據類型。更直白地説,隻有右邊的值對於左邊的變量是可賦值的,賦值語句纔是允許的。
可賦值性的規則對於不同類型有不同要求, 對每個新類型有關的地方我們會專門解釋. 可賦值性的規則對於不同類型有着不同要求對每個新類型特殊的地方我們會專門解釋。對於目前我們已經討論過的類型它的規則是簡單的類型必鬚完全匹配nil可以賦值給任何指針或引用類型的變量。常量§3.6)則有更靈活的賦值規則,因爲這樣可以避免不必要的顯式的類型轉換。
對於目前我們已經討論過的類型, 它的規則是簡單的: 類型必鬚完全匹配, nil 可以賦值給任何指針或引用類型的變量. 常量(§3.6)有更靈活的規則, 這樣可以避免不必要的顯示類型轉換.
對於兩個值是否可以用 `==``!=` 進行相等比較的能力也和可賦值能力有關繫: 對於兩個值是否可以用`==`或`!=`進行相等比較的能力也和可賦值能力有關繫:對於任何類型的值的相等比較,第二個值必鬚是對第一個值類型對應的變量是可賦值的,反之依然。和前面一樣,我們會對每個新類型比較特殊的地方做專門的解釋。
對於任何的比較, 第一個操作必鬚是可用於第二個操作類型的變量的賦值的, 反之依然.
和前面一樣, 我們會對每個新類型比較有關的地方會做專門解釋.

View File

@ -1,28 +1,28 @@
## 2.4. 賦值 ## 2.4. 賦值
使用賦值語句可以更新一個變量的值, 最簡單的賦值語句是將要被賦值的變量放在 `=` 的左邊, 新值的表達式放在 `=` 右邊. 使用賦值語句可以更新一個變量的值,最簡單的賦值語句是將要被賦值的變量放在=的左邊,新值的表達式放在=的右邊。
```Go ```Go
x = 1 // 命令變量的賦值 x = 1 // 命令變量的賦值
*p = true // 通過指針間接賦值 *p = true // 通過指針間接賦值
person.name = "bob" // 結構體字段賦值 person.name = "bob" // 結構體字段賦值
count[x] = count[x] * scale // 數組, 切片 或 字典的 元素賦值 count[x] = count[x] * scale // 數組、slice或map的元素賦值
``` ```
特定的賦值語句和二元算術複合操作有一個簡潔形式, 例如上面最後的語句可以重寫爲: 特定的二元算術運算符和賦值語句的複合操作有一個簡潔形式,例如上面最後的語句可以重寫爲:
```Go ```Go
count[x] *= scale count[x] *= scale
``` ```
這樣可以省去對變量表達式的重複計算. 這樣可以省去對變量表達式的重複計算
數值變量也可以支持 `++` 遞增和 `--` 遞減語句: 數值變量也可以支持`++`遞增和`--`遞減語句(譯註:自增和自減是語句,而不是表達式,因此`x = i++`之類的表達式是錯誤的):
```Go ```Go
v := 1 v := 1
v++ // 等價方式 v = v + 1; v 變成 2 v++ // 等價方式 v = v + 1v 變成 2
v-- // 等價方式 v = v - 1; v 變成 1 v-- // 等價方式 v = v - 1v 變成 1
``` ```
{% include "./ch2-04-1.md" %} {% include "./ch2-04-1.md" %}