Go 語言基礎 陣列、切片、對映

Meng小羽發表於2020-06-18

友情提示:此篇文章大約需要閱讀 5分鐘14秒,不足之處請多指教,感謝你的閱讀。? 訂閱本站

在 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);
}

遍歷對映的鍵值對時的順序是隨機,若要有序的獲得對映的鍵值對,則需要先遍歷出對映的鍵存到一個切片中,然後排序該切片,最後遍歷該切片,按切片中元素的順序去對映中取對應的值

本作品採用《CC 協議》,轉載必須註明作者和本文連結
Meng小羽

相關文章