1. 程式人生 > >Go語言基礎:array、slice、make和new操作、map

Go語言基礎:array、slice、make和new操作、map

array

陣列宣告和賦值

go的陣列宣告跟C語言很相似,除了陣列型別放在變數名後面【這點跟變數的宣告一樣】。
陣列的定義格式:

//一維陣列
var 陣列名[n] 陣列型別 //需要注意的是:'[n]'可以寫成'[...]',go會自動根據元素個數來計算長度,
//我猜應該是編譯的時候計算的吧
//二維陣列
var 陣列名[2][n]int{[n]陣列型別{..},[n]陣列型別{}}

陣列的宣告和賦值:

//一維陣列
var ar = [5]byte {'a', 'b', 'c', 'd', 'e'}
//也可以
ar := [5]byte {'a', 'b', 'c', 'd', 'e'}//注意這個只能是函式內部定義,也就是區域性變數
//二維陣列 var arr = [2][4]int{ [4]int{1, 2, 3}, [4]int{4, 5, 6} } //可以省略{}中的[4]int var arr = [2][4]int{ {1, 2, 3}, {4, 5, 6} }

陣列容量和長度

Go中,函式cap()len()均輸出陣列的容量跟長度,不難發現數組的容量跟長度是一樣的。

slice

Go的陣列用的是C的思想,那麼slice則用的是java的思想。slice在記憶體中的本質其實也是陣列,體現為連續的記憶體塊。但是它與陣列又有不同,陣列一旦定義好了,它的大小也就固定了;而slice的大小是可以變化的,但又不是java中真正意義上的動態陣列,而是陣列的引用,是一個引用型別。
slice的宣告跟陣列的宣告一樣,只是不需要長度。


slice的宣告:

var fslice []int//注意這裡沒有長度,所以不要把它認為是陣列哦
//同樣也可以
slice := []int{1,2,3}

sliced的宣告和賦值:

var ar = []byte {'a', 'b', 'c', 'd', 'e'}
//也可以
ar := []byte {'a', 'b', 'c', 'd', 'e'}//注意這個只能是函式內部定義,也就是區域性變數

我們也可以從一個數組或者一個已經存在的slice中再次宣告。slice 通過 array[i:j] 來獲取,其中 i是陣列的開始位置, j 是結束位置,但不包含 array[j] ,它的長度是 j-i

//宣告一個數組
var Array_ori = [11]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'}

//宣告兩個slice
var Slice_a,Slice_b[]byte

//Slice_a指向陣列Array_ori,第2個元素`Array_ori[2-1]`開始,第5個元素`Array_ori[5-1]`結束
slice_a = Array_ori[2:5]

//slice1指向陣列Slice_a,第3個元素`Slice_a[3-1]`開始,第5個元素`Slice_a[5-1]`結束
slice_b = Slice_a[3:5]//先自己想下會輸出什麼

其資料結構如下所示:
這裡寫圖片描述

根據上圖,不難推匯出Array_ori, slice_a, slice_b的內容輸出如下:

Array_ori[a b c d e f g h i j k]
slice_a[c d e]
slice_b[f g]

是不是對slice有種似曾相識的感覺,沒錯,感覺跟C的指標很像,一開始學的時候感覺有java的動態陣列的思想,這會又有C的指標思想,寶寶好凌亂啊。

slice的幾個內建函式

  • cap():slice的最大容量,上例中的 Slice_a和Slice_b的cap()值分別為8和5。正式由於Slice_a容量為8,所以給Slice_b的賦值是有效的
  • len():slice的長度,上例已有介紹,Slice_a和Slice_b的len()值分別為3和2
  • append():向 slice 裡面追加一個或者多個元素,然後返回一個和 slice 一樣型別的slice
  • copy():函式 copy 從源 slice 的 src 中複製元素到目標 dst ,並且返回複製的元素的個數

make和new操作

make跟new都可以用於記憶體分配。

  • new用於各種型別的記憶體分配,本質上跟java的new的功能是一樣的。new(T)返回了一個指標,指向新分配的型別 T 的零值。
  • make只能用於給slice、map和channel型別的記憶體分配,並且返回一個有初始值(非零)的 T 型別,而不是指標 T。

map

map跟Pythoon的字典概念一樣,凌亂了,又開始有python的思想了。關鍵是不懂python啊,不過沒關係,後面我會學它的。

map的格式:

map[keyType] valueType

map的宣告:

  • 使用map關鍵字: var map_variable map[keyType]valueType
  • 使用 make 函式,返回一個 map 給 map_variable:map_variable = make(map[keyType]valueType)

map的宣告和賦值

var numbers map[string] int
// 另一種 map 的宣告方式
numbers := make(map[string]int)

numbers["one"] = 1 //賦值 key是“one”,值是1
numbers["ten"] = 10 //賦值
numbers["three"] = 3

fmt.Println("第三個數字是: ", numbers["three"]) // 讀取資料打印出來如:第三個數字是: 3

map注意事項:

  • map 是無序的,每次打印出來的 map 都會不一樣,它不能通過 index 獲取,而必須通過 key 獲取
  • map 的長度是不固定的,也就是和 slice 一樣,也是一種引用型別
  • 內建的 len 函式同樣適用於 map ,返回 map 擁有的 key 的數量
  • map 的值可以很方便的修改,通過 numbers[“one”]=11 可以很容易的把 key 為 one的字典值改為 11
  • map 的初始化可以通過 key:val 的方式初始化值,同時 map 內建有判斷是否存在 key 的方式;比如:map_variable := map[string]string{"a": "1", "b": "2", "c": "3"}
  • 通過 delete 刪除 map 的元素,函式原型delete(map_variable, key)