Add more term fixes and markdown format fixes
This commit is contained in:
@@ -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 為 v1,vname2 為 v2,vname3 為 v3
|
||||
@@ -34,8 +34,8 @@ var variableName type = value
|
||||
var vname1, vname2, vname3 type= v1, v2, v3
|
||||
```
|
||||
你是不是覺得上面這樣的定義有點繁瑣?沒關係,因為 Go 語言的設計者也發現了,有一種寫法可以讓它變得簡單一點。我們可以直接忽略型別宣告,那麼上面的程式碼變成這樣了:
|
||||
```Go
|
||||
|
||||
```Go
|
||||
/*
|
||||
定義三個變數,它們分別初始化為相應的值
|
||||
vname1 為 v1,vname2 為 v2,vname3 為 v3
|
||||
@@ -44,8 +44,8 @@ var vname1, vname2, vname3 type= v1, v2, v3
|
||||
var vname1, vname2, vname3 = v1, v2, v3
|
||||
```
|
||||
你覺得上面的還是有些繁瑣?好吧,我也覺得。讓我們繼續簡化:
|
||||
```Go
|
||||
|
||||
```Go
|
||||
/*
|
||||
定義三個變數,它們分別初始化為相應的值
|
||||
vname1 為 v1,vname2 為 v2,vname3 為 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`。
|
||||
|
||||
這就是全部嗎?No!Go 還支援複數。它的預設型別是`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` 的時候採用,它預設開始值是 0,const 中每增加一行加 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>)
|
||||
|
||||
Reference in New Issue
Block a user