Meng小羽

Debug客栈

永远相信美好的事情即将发生! 非标准程序猿 / 🧑‍💻爱编码 / 📹爱摄影 / ⛰️爱徒步 / ❤️更爱女朋友 / 米家好物推荐官 关注我哦,让我们一起变得更强~
github
x
bilibili
zhihu
youtube
follow
email

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

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

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

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。