mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-08-04 15:01:46 +00:00
update tw
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
## 3.4. 佈爾型
|
||||
|
||||
|
||||
一箇佈爾類型的值隻有兩種 true 和 false. if 和 for 語句的條件部分都是佈爾類型的值, 並且 == 和 < 等比較操作也會產生佈爾型的值. 一元操作符 `!` 對應邏輯非操作, 因此 `!true` 的值為 `false`, 也可以說是 `(!true==false)==true`, 雖然錶達方式不一樣, 不過我們一般會採用簡潔的佈爾錶達式, 就像用 x 來錶示 `x==true`.
|
||||
一個佈爾類型的值隻有兩種 true 和 false. if 和 for 語句的條件部分都是佈爾類型的值, 並且 == 和 < 等比較操作也會產生佈爾型的值. 一元操作符 `!` 對應邏輯非操作, 因此 `!true` 的值爲 `false`, 也可以說是 `(!true==false)==true`, 雖然表達方式不一樣, 不過我們一般會採用簡潔的佈爾表達式, 就像用 x 來表示 `x==true`.
|
||||
|
||||
佈爾值可以和 && (AND) 和 || (OR) 操作符結閤, 並且可能會有短路行為: 如果運算符左邊值已經可以確定整箇佈爾錶達式的值, 那麽運算符右邊的值將不在被評估, 因此下麪的錶達式總是安全的:
|
||||
佈爾值可以和 && (AND) 和 || (OR) 操作符結合, 並且可能會有短路行爲: 如果運算符左邊值已經可以確定整個佈爾表達式的值, 那麽運算符右邊的值將不在被評估, 因此下面的表達式總是安全的:
|
||||
|
||||
```Go
|
||||
s != "" && s[0] == 'x'
|
||||
@@ -11,7 +11,7 @@ s != "" && s[0] == 'x'
|
||||
|
||||
其中 s[0] 應用於空字符串會導緻 panic 異常.
|
||||
|
||||
因為 `&&` 的優先級比 `||` 高 (助記: `&&` 對應邏輯乘法, `||` 對應邏輯加法, 乘法比加法優先級要高), 下麪形式的佈爾錶達式是不需要加小括弧的:
|
||||
因爲 `&&` 的優先級比 `||` 高 (助記: `&&` 對應邏輯乘法, `||` 對應邏輯加法, 乘法比加法優先級要高), 下面形式的佈爾表達式是不需要加小括弧的:
|
||||
|
||||
```Go
|
||||
if 'a' <= c && c <= 'z' ||
|
||||
@@ -21,7 +21,7 @@ if 'a' <= c && c <= 'z' ||
|
||||
}
|
||||
```
|
||||
|
||||
佈爾值並不會隱式轉換為數字值0或1, 反之亦然. 必須使用一箇顯式的if語句輔助轉換:
|
||||
佈爾值並不會隱式轉換爲數字值0或1, 反之亦然. 必鬚使用一個顯式的if語句輔助轉換:
|
||||
|
||||
```Go
|
||||
i := 0
|
||||
@@ -30,7 +30,7 @@ if b {
|
||||
}
|
||||
```
|
||||
|
||||
如果需要經常做類似的轉換, 包裝成一箇函數會更方便:
|
||||
如果需要經常做類似的轉換, 包裝成一個函數會更方便:
|
||||
|
||||
```Go
|
||||
// btoi returns 1 if b is true and 0 if false.
|
||||
@@ -42,7 +42,7 @@ func btoi(b bool) int {
|
||||
}
|
||||
```
|
||||
|
||||
數字到佈爾型的逆轉換則非常簡單, 不過為了保持對稱, 我們也可以包裝一箇函數:
|
||||
數字到佈爾型的逆轉換則非常簡單, 不過爲了保持對稱, 我們也可以包裝一個函數:
|
||||
|
||||
```Go
|
||||
// itob reports whether i is non-zero.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
### 3.5.1. 字符串麪值
|
||||
### 3.5.1. 字符串面值
|
||||
|
||||
|
||||
字符串值也可以用字符串麪值方式編寫, 隻要將一係列字節序列包含在雙引號卽可:
|
||||
字符串值也可以用字符串面值方式編寫, 隻要將一繫列字節序列包含在雙引號卽可:
|
||||
|
||||
```
|
||||
"Hello, 世界"
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||

|
||||
|
||||
因為Go語言源文件總是用UTF8編碼, 並且Go的文本字符串也以UTF8編碼的方式處理, 我們可以將Unicode碼點也寫到字符串麪值中.
|
||||
因爲Go語言源文件總是用UTF8編碼, 並且Go的文本字符串也以UTF8編碼的方式處理, 我們可以將Unicode碼點也寫到字符串面值中.
|
||||
|
||||
在一箇雙引號包含的字符串麪值中, 可以用以反斜槓\開頭的轉義序列插入任意的數據. 下麪換行, 迴車和 製錶符等常見的ASCII控製代碼的轉義方式:
|
||||
在一個雙引號包含的字符串面值中, 可以用以反斜槓\開頭的轉義序列插入任意的數據. 下面換行, 迴車和 製表符等常見的ASCII控製代碼的轉義方式:
|
||||
|
||||
```
|
||||
\a 響鈴
|
||||
@@ -19,18 +19,18 @@
|
||||
\f 換頁
|
||||
\n 換行
|
||||
\r 迴車
|
||||
\t 製錶符
|
||||
\v 垂直製錶符
|
||||
\' 單引號 (隻用在 '\'' 形式的rune符號麪值中)
|
||||
\" 雙引號 (隻用在 "..." 形式的字符串麪值中)
|
||||
\t 製表符
|
||||
\v 垂直製表符
|
||||
\' 單引號 (隻用在 '\'' 形式的rune符號面值中)
|
||||
\" 雙引號 (隻用在 "..." 形式的字符串面值中)
|
||||
\\ 反斜槓
|
||||
```
|
||||
|
||||
可以通過十六進製或八進製轉義在字符串麪值包含任意的字節. 一箇十六進製的轉義是 \xhh, 其中兩箇h錶示十六進製數字(大寫或小寫都可以). 一箇八進製轉義是 \ooo, 包含三箇八進製的o數字(0到7), 但是不能超過\377. 每一箇單一的字節錶達一箇特定的值. 稍後我們將看到如何將一箇Unicode碼點寫到字符串麪值中.
|
||||
可以通過十六進製或八進製轉義在字符串面值包含任意的字節. 一個十六進製的轉義是 \xhh, 其中兩個h表示十六進製數字(大寫或小寫都可以). 一個八進製轉義是 \ooo, 包含三個八進製的o數字(0到7), 但是不能超過\377. 每一個單一的字節表達一個特定的值. 稍後我們將看到如何將一個Unicode碼點寫到字符串面值中.
|
||||
|
||||
一箇原生的字符串麪值形式是 `...`, 使用反引號 ``` 代替雙引號. 在原生的字符串麪值中, 沒有轉義操作; 全部的內容都是字麪的意思, 包含退格和換行, 因此一箇程序中的原生字符串麪值可能跨越多行. 唯一的特殊處理是是刪除迴車以保證在所有平檯上的值都是一樣的, 包括那些把迴車也放入文本文件的係統.
|
||||
一個原生的字符串面值形式是 `...`, 使用反引號 ``` 代替雙引號. 在原生的字符串面值中, 沒有轉義操作; 全部的內容都是字面的意思, 包含退格和換行, 因此一個程序中的原生字符串面值可能跨越多行. 唯一的特殊處理是是刪除迴車以保証在所有平檯上的值都是一樣的, 包括那些把迴車也放入文本文件的繫統.
|
||||
|
||||
原生字符串麪值用於編寫正則錶達式會很方便, 因為正則錶達式往往會包含很多反斜槓. 原生字符串麪值衕時廣氾應用於HTML模闆, JSON麪值, 命令行提示信息, 以及那些需要擴展到多行的場景.
|
||||
原生字符串面值用於編寫正則表達式會很方便, 因爲正則表達式往往會包含很多反斜槓. 原生字符串面值同時廣汎應用於HTML模闆, JSON面值, 命令行提示信息, 以及那些需要擴展到多行的場景.
|
||||
|
||||
```Go
|
||||
const GoUsage = `Go is a tool for managing Go source code.
|
||||
|
@@ -1,13 +1,13 @@
|
||||
### 3.5.2. Unicode
|
||||
|
||||
|
||||
在很久以前, 世界比較簡單的, 起碼計算機就隻有一箇ASCII字符集: 美國信息交換標準代碼. ASCII, 更準確地說是美國的ASCII, 使用 7bit 來錶示 128 箇字符: 包含英文字母的大小寫, 數字, 各種標點符號和設置控製符. 對於早期的計算機程序, 這些足夠了, 但是這也導緻了世界上很多其他地區的用戶無法直接使用自己的書寫係統. 隨着互聯網的發展, 混閤多種語言的數據變了很常見. 如何有效處理這些包含了各種語言的豐富多樣的數據呢?
|
||||
在很久以前, 世界比較簡單的, 起碼計算機就隻有一個ASCII字符集: 美國信息交換標準代碼. ASCII, 更準確地說是美國的ASCII, 使用 7bit 來表示 128 個字符: 包含英文字母的大小寫, 數字, 各種標點符號和設置控製符. 對於早期的計算機程序, 這些足夠了, 但是這也導緻了世界上很多其他地區的用戶無法直接使用自己的書寫繫統. 隨着互聯網的發展, 混合多種語言的數據變了很常見. 如何有效處理這些包含了各種語言的豐富多樣的數據呢?
|
||||
|
||||
答案就是使用Unicode(unicode.org), 它收集了這箇世界上所有的書寫係統, 包括重音符號和其他變音符號, 製錶符和迴車符, 還有很多神祕符號, 每箇符號都分配一箇Unicode碼點, Unicode碼點對應Go語言中的rune類型.
|
||||
答案就是使用Unicode(unicode.org), 它收集了這個世界上所有的書寫繫統, 包括重音符號和其他變音符號, 製表符和迴車符, 還有很多神祕符號, 每個符號都分配一個Unicode碼點, Unicode碼點對應Go語言中的rune類型.
|
||||
|
||||
第八版本的Unicode標準收集了超過120,000箇字符, 涵蓋超過100種語言. 這些在計算機程序和數據中是如何體現的那? 通用的錶示一箇Unicode碼點的數據類型是int32, 也就是Go語言中rune對應的類型; 它的衕義詞rune符文正是這箇意思.
|
||||
第八版本的Unicode標準收集了超過120,000個字符, 涵蓋超過100種語言. 這些在計算機程序和數據中是如何體現的那? 通用的表示一個Unicode碼點的數據類型是int32, 也就是Go語言中rune對應的類型; 它的同義詞rune符文正是這個意思.
|
||||
|
||||
我們可以將一箇符文序列錶示為一箇int32序列. 這種編碼方式叫UTF-32或UCS-4, 每箇Unicode碼點都使用衕樣的大小32bit來錶示. 這種方式比較簡單統一, 它會浪費很多存儲空間, 因為大數據計算機可讀的文本是ASCII字符, 本來每箇ASCII字符隻需要8bit或1字節就能錶示. 卽使是常用的字符也遠少於65,536箇, 也就是說用16bit編碼方式就能錶達常用字符. 但是, 還有更好的編碼方法嗎?
|
||||
我們可以將一個符文序列表示爲一個int32序列. 這種編碼方式叫UTF-32或UCS-4, 每個Unicode碼點都使用同樣的大小32bit來表示. 這種方式比較簡單統一, 它會浪費很多存儲空間, 因爲大數據計算機可讀的文本是ASCII字符, 本來每個ASCII字符隻需要8bit或1字節就能表示. 卽使是常用的字符也遠少於65,536個, 也就是說用16bit編碼方式就能表達常用字符. 但是, 還有更好的編碼方法嗎?
|
||||
|
||||
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
除了字符串, 字符, 字節 之間的轉換, 字符串和數值之間的轉換也比較常見. 由 strconv 包提供這類轉換功能.
|
||||
|
||||
將一箇整數轉為字符串, 一種方法是用 fmt.Sprintf; 另一箇方法是用 strconv.Itoa(“整數到ASCII”):
|
||||
將一個整數轉爲字符串, 一種方法是用 fmt.Sprintf; 另一個方法是用 strconv.Itoa(“整數到ASCII”):
|
||||
|
||||
```Go
|
||||
x := 123
|
||||
@@ -11,28 +11,28 @@ y := fmt.Sprintf("%d", x)
|
||||
fmt.Println(y, strconv.Itoa(x)) // "123 123"
|
||||
```
|
||||
|
||||
FormatInt和FormatUint可以用不衕的進製來格式化數字:
|
||||
FormatInt和FormatUint可以用不同的進製來格式化數字:
|
||||
|
||||
```Go
|
||||
fmt.Println(strconv.FormatInt(int64(x), 2)) // "1111011"
|
||||
```
|
||||
|
||||
fmt.Printf 函數的 %b, %d, %u, 和 %x 等參數提供功能往往比strconv 包的 Format 函數方便很多, 特彆是在需要包含附加信息的時候:
|
||||
fmt.Printf 函數的 %b, %d, %u, 和 %x 等參數提供功能往往比strconv 包的 Format 函數方便很多, 特別是在需要包含附加信息的時候:
|
||||
|
||||
```Go
|
||||
s := fmt.Sprintf("x=%b", x) // "x=1111011"
|
||||
```
|
||||
|
||||
如果要將一箇字符串解析為整數, 可以使用 strconv 包的 Atoi 或 ParseInt 函數, 還有用於解析無符號整數的 ParseUint 函數:
|
||||
如果要將一個字符串解析爲整數, 可以使用 strconv 包的 Atoi 或 ParseInt 函數, 還有用於解析無符號整數的 ParseUint 函數:
|
||||
|
||||
```Go
|
||||
x, err := strconv.Atoi("123") // x is an int
|
||||
y, err := strconv.ParseInt("123", 10, 64) // base 10, up to 64 bits
|
||||
```
|
||||
|
||||
ParseInt 函數的第三箇參數是用於指定整型數的大小; 例如16錶示int16, 0則錶示int. 在任何情況下, 返迴的結果 y 總是 int64 類型, 你可以通過強製類型轉換將它轉為更小的整數類型.
|
||||
ParseInt 函數的第三個參數是用於指定整型數的大小; 例如16表示int16, 0則表示int. 在任何情況下, 返迴的結果 y 總是 int64 類型, 你可以通過強製類型轉換將它轉爲更小的整數類型.
|
||||
|
||||
有時候也會使用 fmt.Scanf 來解析輸入的字符串和數字, 特彆是噹字符串和數字混閤在一行的時候, 它可以靈活處理不完整或不規則的輸入.
|
||||
有時候也會使用 fmt.Scanf 來解析輸入的字符串和數字, 特別是當字符串和數字混合在一行的時候, 它可以靈活處理不完整或不規則的輸入.
|
||||
|
||||
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
## 3.5. 字符串
|
||||
|
||||
一箇字符串是一箇不可改變的字節序列. 字符串可以包含任意的數據, 包括字節值0, 但是通常包含人類可讀的文本. 文本字符串通常被解釋為採用UTF8編碼的Unicode碼點(rune)序列, 我們稍後會詳細討論這箇問題.
|
||||
一個字符串是一個不可改變的字節序列. 字符串可以包含任意的數據, 包括字節值0, 但是通常包含人類可讀的文本. 文本字符串通常被解釋爲採用UTF8編碼的Unicode碼點(rune)序列, 我們稍後會詳細討論這個問題.
|
||||
|
||||
內置的 len 函數可以返迴一箇字符串的字節數目(不是rune字符數目), 索引操作 s[i] 返迴第i箇字節的字節值, i 必須滿足 0 ≤ i< len(s) 條件約束.
|
||||
內置的 len 函數可以返迴一個字符串的字節數目(不是rune字符數目), 索引操作 s[i] 返迴第i個字節的字節值, i 必鬚滿足 0 ≤ i< len(s) 條件約束.
|
||||
|
||||
```Go
|
||||
s := "hello, world"
|
||||
@@ -18,17 +18,17 @@ Attempting to access a byte outside this range results in a panic:
|
||||
c := s[len(s)] // panic: index out of range
|
||||
```
|
||||
|
||||
第i箇字節並不一定是字符串的第i箇字符, 因此對於非ASCII字符的UTF8編碼會要兩箇或多箇字節. 我們簡單說下字符的工作方式.
|
||||
第i個字節並不一定是字符串的第i個字符, 因此對於非ASCII字符的UTF8編碼會要兩個或多個字節. 我們簡單說下字符的工作方式.
|
||||
|
||||
子字符串操作s[i:j]基於原始的s字符串的第i箇字節開始到第j箇字節(並不包含j本身)生成一箇新字符串. 生成的子字符串將包含 j-i 箇字節.
|
||||
子字符串操作s[i:j]基於原始的s字符串的第i個字節開始到第j個字節(並不包含j本身)生成一個新字符串. 生成的子字符串將包含 j-i 個字節.
|
||||
|
||||
```Go
|
||||
fmt.Println(s[0:5]) // "hello"
|
||||
```
|
||||
|
||||
衕樣, 如果索引超齣字符串範圍或者j小於i的話將導緻panic異常.
|
||||
同樣, 如果索引超齣字符串範圍或者j小於i的話將導緻panic異常.
|
||||
|
||||
不管i還是j都可能被忽略, 噹它們被忽略時將採用0作為開始位置, 採用 len(s) 作為接受的位置.
|
||||
不管i還是j都可能被忽略, 當它們被忽略時將採用0作爲開始位置, 採用 len(s) 作爲接受的位置.
|
||||
|
||||
```Go
|
||||
fmt.Println(s[:5]) // "hello"
|
||||
@@ -36,16 +36,16 @@ fmt.Println(s[7:]) // "world"
|
||||
fmt.Println(s[:]) // "hello, world"
|
||||
```
|
||||
|
||||
其中 + 操作符將兩箇字符串鏈接構造一箇新字符串:
|
||||
其中 + 操作符將兩個字符串鏈接構造一個新字符串:
|
||||
|
||||
```Go
|
||||
fmt.Println("goodbye" + s[5:]) // "goodbye, world"
|
||||
```
|
||||
|
||||
字符串可以用 == 和 < 進行比較; 比較通過逐箇字節比較完成的, 因此比較的結果是字符串自然編碼的順序.
|
||||
字符串可以用 == 和 < 進行比較; 比較通過逐個字節比較完成的, 因此比較的結果是字符串自然編碼的順序.
|
||||
|
||||
|
||||
字符串的值是不可變的: 一箇字符串包含的字節序列永遠不會被改變, 噹然我們也可以給一箇字符串變量分配一箇新字符串值. 可以像下麪這樣將一箇字符串追加到另一箇字符串
|
||||
字符串的值是不可變的: 一個字符串包含的字節序列永遠不會被改變, 當然我們也可以給一個字符串變量分配一個新字符串值. 可以像下面這樣將一個字符串追加到另一個字符串
|
||||
|
||||
```Go
|
||||
s := "left foot"
|
||||
@@ -53,20 +53,20 @@ t := s
|
||||
s += ", right foot"
|
||||
```
|
||||
|
||||
這並不會導緻原始的字符串值被改變, 但是 s 將因為 += 語句持有一箇新的字符串值, 但是 t 依然是包含原先的字符串值.
|
||||
這並不會導緻原始的字符串值被改變, 但是 s 將因爲 += 語句持有一個新的字符串值, 但是 t 依然是包含原先的字符串值.
|
||||
|
||||
```Go
|
||||
fmt.Println(s) // "left foot, right foot"
|
||||
fmt.Println(t) // "left foot"
|
||||
```
|
||||
|
||||
因為字符串是不可脩改的, 因此嘗試脩改字符串內部數據的操作是被禁止的:
|
||||
因爲字符串是不可脩改的, 因此嘗試脩改字符串內部數據的操作是被禁止的:
|
||||
|
||||
```Go
|
||||
s[0] = 'L' // compile error: cannot assign to s[0]
|
||||
```
|
||||
|
||||
不變性意味如果兩箇字符串共享相衕的底層數據是安全的, 這使得復製任何長度的字符串代價是低廉的. 衕樣, 一箇字符串 s 和對應的子字符串 s[7:] 也可以安全地共享相衕的內存, 因此字符串切片操作代價也是低廉的. 在這兩種情況下都沒有必要分配新的內存. 圖3.4 演示了一箇字符串和兩箇字串共享相衕的底層數據.
|
||||
不變性意味如果兩個字符串共享相同的底層數據是安全的, 這使得復製任何長度的字符串代價是低廉的. 同樣, 一個字符串 s 和對應的子字符串 s[7:] 也可以安全地共享相同的內存, 因此字符串切片操作代價也是低廉的. 在這兩種情況下都沒有必要分配新的內存. 圖3.4 演示了一個字符串和兩個字串共享相同的底層數據.
|
||||
|
||||
|
||||
{% include "./ch3-05-1.md" %}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# 第3章 基礎數據類型
|
||||
|
||||
雖然從底層而言,所有的數據都是比特,但計算機操作的是固定位數的數,如整數、浮點數、比特組、內存地址。將這些數,進一步組織在一起,可錶達更多的對象,如數據包、像素點、詩歌,甚至任何對象.Go提供了豐富的數據組織形式,這依賴於Go內置的數據類型。這些內置的數據類型,兼顧了硬件的特性和錶達復雜數據結構的便捷性。
|
||||
雖然從底層而言,所有的數據都是比特,但計算機操作的是固定位數的數,如整數、浮點數、比特組、內存地址。將這些數,進一步組織在一起,可表達更多的對象,如數據包、像素點、詩歌,甚至任何對象.Go提供了豐富的數據組織形式,這依賴於Go內置的數據類型。這些內置的數據類型,兼顧了硬件的特性和表達復雜數據結構的便捷性。
|
||||
|
||||
Go將數據類型分為四類:基礎類型、復閤類型、引用類型和接口類型。本章介紹基礎類型,包括:數字,字符串和佈爾型。復閤數據類型——數組(§4.1)和結構體(§4.2)——通過組閤簡單類型,錶達更加復雜的數據結構。引用類型包括指鍼(§2.3.2)、切片(§4.2))字典(§4.3)、函數(§5)、通道(§8).雖然種類很多,但它們都是對程序中一個變量或狀態的間接引用。這意味着對任一引用的脩改都會影響所有該引用的拷貝。我們將在第7章介紹接口類型。
|
||||
Go將數據類型分爲四類:基礎類型、復合類型、引用類型和接口類型。本章介紹基礎類型,包括:數字,字符串和佈爾型。復合數據類型——數組(§4.1)和結構體(§4.2)——通過組合簡單類型,表達更加復雜的數據結構。引用類型包括指鍼(§2.3.2)、切片(§4.2))字典(§4.3)、函數(§5)、通道(§8).雖然種類很多,但它們都是對程序中一個變量或狀態的間接引用。這意味着對任一引用的脩改都會影響所有該引用的拷貝。我們將在第7章介紹接口類型。
|
Reference in New Issue
Block a user