在 Go 語言中,為便於存儲及管理使用者資料,其資料結構設計分為陣列 Array、切片 Slice、映射 Map 三種結構。
近期又看了 Go 語言基礎的內容,看了一下這三種結構實現的原理:
陣列 Array#
- 陣列是切片和映射的基礎資料結構;
- 陣列是長度固定的資料型別並且在記憶體中也是連續分配的,固索引陣列資料速度是非常快的;
- 声明陣列時需要指定陣列儲存的型別及數量(陣列的長度);
- 陣列變數的型別包括陣列長度和元素的型別,只有兩部分都相同的陣列才可相互賦值。
創建及初始化#
一旦聲明了陣列,其本身的資料型別及長度都是不可以進行變更。
// 使用陣列字面量聲明陣列
array := [5]int{1, 2, 3, 4, 5}
// 自動推導長度聲明陣列
array := [...]int{1, 2, 3, 4, 5, 6}
// 使用 ... 代替長度,根據初始化元素個數推導
// 聲明陣列並指定特定元素值
array := [5]int{1:10, 2:20}
指標型別#
陣列元素的型別可以為任何內建型別,也可以是某種結構型別,也可以是指標型別。
// 聲明一個元素長度為 3 的指向字串的指標陣列
var array1 [3]*string
// 為指標陣列指定元素
*array1[0] = "demo0"
*array1[1] = "demo1"
*array1[2] = "demo2"
多維陣列#
陣列本身是一維資料,多維陣列是由多個陣列組合而來的。
// 聲明一個二維陣列
var array = [3][2]int
// 聲明了一個兩個維度為 3 和 2 的元素
// 初始化二維陣列
var array = [3][2]int{ {1, 2}, {3, 4}, {5, 6}}
在函數間傳遞陣列:由於在函數間傳遞變數時,傳遞的總是變數的值的副本,所以在傳遞陣列變數時將拷貝整個陣列!在定義函數時,對於較大的資料型別應該把參數設計為指標型別,這樣在調用函數時,只需在堆疊上分配給每個指標 8 位元組的記憶體,但這意味著會改變指標指向的值 (共享的記憶體),其實大部分情況下應該使用切片型別,而不是陣列。
切片 Slice#
- 切片 slice 是引用型別,它引用了其指標欄位所指向的底層陣列的一部分或全部;
- 切片是圍繞動態陣列的概念構建的;
- 切片的動態增長是通過 append 來實現的;
- 縮小則是通過對它再次切片來實現,通過再次切片獲得的新切片將和原切片共享底層陣列,它們的指標指向同一個底層陣列。
創建及初始化#
切片型別有 3 個欄位:
- 指標:指向切片所包含的第一個元素在底層陣列中的地址;
- 長度:切片所包含的底層陣列的元素的個數(切片可訪問的元素的個數);
- 容量:切片允許增長到的最大元素個數,即底層陣列的長度。
make 和切片字面量
// 使用 make 創建一個切片
slice := make([]int, 3)
// 創建一個具有長度和容量的切片
slice := make([]int, 1, 6)
// 長度為 1,容量為 6 個元素
nil 和空切片
// nil 字串切片
var slice []string
// 空切片
slice := []int{}
// 空的整形切片
由於切片只是引用了底層陣列,底層陣列的資料並不屬於切片本身,所以一個切片只需要 24 位元組的記憶體 (在 64 位元機器上):指標欄位 8 位元組、長度欄位 8 位元組、容量欄位 8 位元組。所以在函數之間直接傳遞切片是高效的,只需分配 24 位元組的堆疊記憶體。
len
函數可返還切片的長度、cap
函數可返還切片的容量。
映射 Map#
- 映射 map 是用來儲存一系列的無序鍵值對;
- 映射是無序的集合,其實現使用了雜湊表;
- 映射的雜湊表包含一組桶,每個桶裡儲存著一部分鍵值對;
- 映射內部使用了兩個陣列:
- 第一個陣列:儲存著用於選擇桶的雜湊鍵的高八位值,該陣列用於區分每個鍵值對要存在哪個桶裡;
- 第二個陣列:每個桶裡都有一個位元組陣列,先依次儲存了該桶裡的所有鍵,之後儲存了該桶的所有值;
創建及初始化#
// 創建一個映射 儲存學生資訊
students := map[string]string{
"name" : "mengxiaoyu",
"age" : "22",
"sex" : "boy",
"hobby": "pingpang",
}
// 顯示映射所有資訊
for key, value := range students{
fmt.printf("key:%s, \t value:%s\n", key, value);
}
遍歷映射的鍵值對時的順序是隨機,若要有序的獲得映射的鍵值對,則需要先遍歷出映射的鍵存到一個切片中,然後排序該切片,最後遍歷該切片,按切片中元素的順序去映射中取對應的值。