Add more term fixes and markdown format fixes

This commit is contained in:
Will
2019-03-03 00:40:37 +08:00
parent accc3cc768
commit d5355ad2ec
69 changed files with 573 additions and 393 deletions

View File

@@ -7,26 +7,26 @@
Go 語言裡面定義變數有多種方式。
使用 `var` 關鍵字是 Go 最基本的定義變數方式,與 C 語言不同的是 Go 把變數型別放在變數名後面:
```Go
```Go
//定義一個名稱為“variableName”型別為"type"的變數
var variableName type
```
定義多個變數
```Go
```Go
//定義三個型別都是“type”的變數
var vname1, vname2, vname3 type
```
定義變數並初始化值
```Go
```Go
//初始化“variableName”的變數為“value”值型別是“type”
var variableName type = value
```
同時初始化多個變數
```Go
```Go
/*
定義三個型別都是"type"的變數,並且分別初始化為相應的值
vname1 為 v1vname2 為 v2vname3 為 v3
@@ -34,8 +34,8 @@ var variableName type = value
var vname1, vname2, vname3 type= v1, v2, v3
```
你是不是覺得上面這樣的定義有點繁瑣?沒關係,因為 Go 語言的設計者也發現了,有一種寫法可以讓它變得簡單一點。我們可以直接忽略型別宣告,那麼上面的程式碼變成這樣了:
```Go
```Go
/*
定義三個變數,它們分別初始化為相應的值
vname1 為 v1vname2 為 v2vname3 為 v3
@@ -44,8 +44,8 @@ var vname1, vname2, vname3 type= v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3
```
你覺得上面的還是有些繁瑣?好吧,我也覺得。讓我們繼續簡化:
```Go
```Go
/*
定義三個變數,它們分別初始化為相應的值
vname1 為 v1vname2 為 v2vname3 為 v3
@@ -60,8 +60,8 @@ vname1, vname2, vname3 := v1, v2, v3
_, b := 34, 35
Go 對於已宣告但未使用的變數會在編譯階段報錯,比如下面的程式碼就會產生一個錯誤:宣告了 `i` 但未使用。
```Go
```Go
package main
func main() {
@@ -73,15 +73,15 @@ func main() {
所謂常數,也就是在程式編譯階段就確定下來的值,而程式在執行時無法改變該值。在 Go 程式中,常數可定義為數值、布林值或字串等型別。
它的語法如下:
```Go
```Go
const constantName = value
//如果需要,也可以明確指定常數的型別:
const Pi float32 = 3.1415926
```
下面是一些常數宣告的例子:
```Go
```Go
const Pi = 3.1415926
const i = 10000
const MaxThread = 10
@@ -95,8 +95,8 @@ Go 常數和一般程式語言不同的是,可以指定相當多的小數位
### Boolean
在 Go 中,布林值的型別為`bool`,值是 `true``false`,預設為`false`
```Go
```Go
//範例程式碼
var isActive bool // 全域性變數宣告
var enabled, disabled = true, false // 忽略型別的宣告
@@ -126,8 +126,8 @@ func test() {
浮點數的型別有 `float32``float64`兩種(沒有 `float` 型別),預設是`float64`
這就是全部嗎NoGo 還支援複數。它的預設型別是`complex128`64 位實數+64 位虛數)。如果需要小一些的,也有`complex64`(32 位實數+32 位虛數)。複數的形式為`RE + IMi`,其中 `RE` 是實數部分,`IM`是虛數部分,而最後的 `i` 是虛數單位。下面是一個使用複數的例子:
```Go
```Go
var c complex64 = 5+5i
//output: (5+5i)
fmt.Printf("Value is: %v", c)
@@ -136,8 +136,8 @@ fmt.Printf("Value is: %v", c)
### 字串
我們在上一節中講過Go 中的字串都是採用`UTF-8`字符集編碼。字串是用一對雙引號(`""`)或反引號(`` ` `` `` ` ``)括起來定義,它的型別是`string`。
```Go
```Go
//範例程式碼
var frenchHello string // 宣告變數為字串的一般方法
var emptyString string = "" // 宣告了一個字串變數,初始化為空字串
@@ -148,15 +148,15 @@ func test() {
}
```
在 Go 中字串是不可變的例如下面的程式碼編譯時會報錯cannot assign to s[0]
```Go
```Go
var s string = "hello"
s[0] = 'c'
```
但如果真的想要修改怎麼辦呢?下面的程式碼可以實現:
```Go
但如果真的想要修改怎麼辦呢?下面的程式碼可以實現:
```Go
s := "hello"
c := []byte(s) // 將字串 s 轉換為 []byte 型別
c[0] = 'c'
@@ -165,16 +165,16 @@ fmt.Printf("%s\n", s2)
```
Go 中可以使用`+`運算子來連線兩個字串:
```Go
```Go
s := "hello,"
m := " world"
a := s + m
fmt.Printf("%s\n", a)
```
修改字串也可寫為:
```Go
```Go
s := "hello"
s = "c" + s[1:] // 字串雖不能更改,但可進行切片(slice)操作
fmt.Printf("%s\n", s)
@@ -191,8 +191,8 @@ fmt.Printf("%s\n", s)
### 錯誤型別
Go 內建有一個 `error` 型別專門用來處理錯誤資訊Go 的 `package` 裡面還專門有一個套件 `errors` 來處理錯誤:
```Go
```Go
err := errors.New("emit macho dwarf: elf header corrupted")
if err != nil {
fmt.Print(err)
@@ -213,8 +213,8 @@ if err != nil {
在 Go 語言中,同時宣告多個常數、變數,或者匯入多個套件時,可採用分組的方式進行宣告。
例如下面的程式碼:
```Go
```Go
import "fmt"
import "os"
@@ -227,8 +227,8 @@ var pi float32
var prefix string
```
可以分組寫成如下形式:
```Go
```Go
import(
"fmt"
"os"
@@ -249,8 +249,8 @@ var(
### iota 列舉
Go 裡面有一個關鍵字 `iota`,這個關鍵字用來宣告 `enum` 的時候採用,它預設開始值是 0const 中每增加一行加 1
```Go
```Go
package main
import (
@@ -293,13 +293,13 @@ Go 之所以會那麼簡潔,是因為它有一些預設的行為:
### array
`array`就是陣列,它的定義方式如下:
```Go
```Go
var arr [n]type
```
在 `[n]type` 中,`n`表示陣列的長度,`type`表示儲存元素的型別。對陣列的操作和其它語言類似,都是透過 `[]` 來進行讀取或賦值:
```Go
```Go
var arr [10]int // 宣告了一個 int 型別的陣列
arr[0] = 42 // 陣列下標是從 0 開始的
arr[1] = 13 // 賦值操作
@@ -309,8 +309,8 @@ fmt.Printf("The last element is %d\n", arr[9]) //回傳未賦值的最後一個
由於長度也是陣列型別的一部分,因此 `[3]int` 與`[4]int`是不同的型別,陣列也就不能改變長度。陣列之間的賦值是值的賦值,即當把一個陣列作為參數傳入函式的時候,傳入的其實是該陣列的副本,而不是它的指標。如果要使用指標,那麼就需要用到後面介紹的 `slice` 型別了。
陣列可以使用另一種 `:=` 來宣告
```Go
```Go
a := [3]int{1, 2, 3} // 宣告了一個長度為 3 的 int 陣列
b := [10]int{1, 2, 3} // 宣告了一個長度為 10 的 int 陣列,其中前三個元素初始化為 1、2、3其它預設為 0
@@ -318,8 +318,8 @@ b := [10]int{1, 2, 3} // 宣告了一個長度為 10 的 int 陣列,其中前
c := [...]int{4, 5, 6} // 可以省略長度而採用`...`的方式Go 會自動根據元素個數來計算長度
```
也許你會說我想陣列裡面的值還是陣列能實現嗎當然囉Go 支援巢狀陣列,即多維陣列。比如下面的程式碼就宣告了一個二維陣列:
```Go
```Go
// 宣告了一個二維陣列,該陣列以兩個陣列作為元素,其中每個陣列中又有 4 個 int 型別的元素
doubleArray := [2][4]int{[4]int{1, 2, 3, 4}, [4]int{5, 6, 7, 8}}
@@ -338,19 +338,19 @@ easyArray := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}}
在很多應用場景中,陣列並不能滿足我們的需求。在初始定義陣列時,我們並不知道需要多大的陣列,因此我們就需要“動態陣列”。在 Go 裡面這種資料結構叫`slice`
`slice`並不是真正意義上的動態陣列,而是一個參考型別。`slice`總是指向一個底層`array``slice`的宣告也可以像 `array` 一樣,只是不需要長度。
```Go
```Go
// 和宣告 array 一樣,只是少了長度
var fslice []int
```
接下來我們可以宣告一個`slice`,並初始化資料,如下所示:
```Go
```Go
slice := []byte {'a', 'b', 'c', 'd'}
```
`slice`可以從一個陣列或一個已經存在的 `slice` 中再次宣告。`slice`透過 `array[i:j]` 來取得,其中 `i` 是陣列的開始位置,`j`是結束位置,但不包含`array[j]`,它的長度是`j-i`。
```Go
```Go
// 宣告一個含有 10 個元素元素型別為 byte 的陣列
var ar = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
@@ -380,8 +380,8 @@ slice 有一些簡便的操作
- 如果從一個陣列裡面直接取得`slice`,可以這樣`ar[:]`,因為預設第一個序列是 0第二個是陣列的長度即等價於`ar[0:len(ar)]`
下面這個例子展示了更多關於 `slice` 的操作:
```Go
```Go
// 宣告一個陣列
var array = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
// 宣告兩個 slice
@@ -405,8 +405,8 @@ bSlice = aSlice[:] // bSlice 包含所有 aSlice 的元素: d,e,f,g
- 一個指標,指向陣列中 `slice` 指定的開始位置
- 長度,即 `slice` 的長度
- 最大長度,也就是 `slice` 開始位置到陣列的最後位置的長度
```Go
```Go
Array_a := [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
Slice_a := Array_a[2:5]
```
@@ -427,8 +427,8 @@ bSlice = aSlice[:] // bSlice 包含所有 aSlice 的元素: d,e,f,g
但當 `slice` 中沒有剩餘空間(即`(cap-len) == 0`)時,此時將動態分配新的陣列空間。回傳的 `slice` 陣列指標將指向這個空間,而原陣列的內容將保持不變;其它參考此陣列的 `slice` 則不受影響。
從 Go1.2 開始 slice 支援了三個參數的 slice之前我們一直採用這種方式在 slice 或者 array 基礎上來取得一個 slice
```Go
```Go
var array [10]int
slice := array[2:4]
```
@@ -445,8 +445,8 @@ slice := array[2:4]
`map`也就是 Python 中字典的概念,它的格式為`map[keyType]valueType`
我們看下面的程式碼,`map`的讀取和設定也類似 `slice` 一樣,透過 `key` 來操作,只是 `slice` 的`index`只能是int型別而 `map` 多了很多型別,可以是`int`,可以是 `string` 及所有完全定義了 `==` 與`!=`操作的型別。
```Go
```Go
// 宣告一個 key 是字串,值為 int 的字典,這種方式的宣告需要在使用之前使用 make 初始化
var numbers map[string]int
// 另一種 map 的宣告方式
@@ -473,7 +473,6 @@ fmt.Println("第三個數字是: ", numbers["three"]) // 讀取資料
透過 `delete` 刪除 `map` 的元素:
```Go
// 初始化一個字典
rating := map[string]float32{"C":5, "Go":4.5, "Python":4.5, "C++":2 }
// map 有兩個回傳值,第二個回傳值,如果不存在 key那麼 ok 為 false如果存在 ok 為 true
@@ -485,17 +484,17 @@ if ok {
}
delete(rating, "C") // 刪除 key 為 C 的元素
```
上面說過了,`map`也是一種參考型別,如果兩個 `map` 同時指向一個底層,那麼一個改變,另一個也相應的改變:
```Go
上面說過了,`map`也是一種參考型別,如果兩個 `map` 同時指向一個底層,那麼一個改變,另一個也相應的改變:
```Go
m := make(map[string]string)
m["Hello"] = "Bonjour"
m1 := m
m1["Hello"] = "Salut" // 現在 m["hello"]的值已經是 Salut 了
```
### make、new 操作
`make`用於內建型別(`map`、`slice` 和`channel`)的記憶體分配。`new`用於各種型別的記憶體分配。
@@ -518,8 +517,8 @@ m1["Hello"] = "Salut" // 現在 m["hello"]的值已經是 Salut 了
## 零值
關於“零值”,所指並非是空值,而是一種“變數未填充前”的預設值,通常為 0。
此處羅列 部分類型 的 “零值”
```Go
```Go
int 0
int8 0
int32 0
@@ -531,8 +530,8 @@ float32 0 //長度為 4 byte
float64 0 //長度為 8 byte
bool false
string ""
```
## links
* [目錄](<preface.md>)
* 上一章: [你好,Go](<02.1.md>)