數組、切片、哈希表
介紹
數組和切片是 Go 語言中常見的數據結構,很多剛使用 Go 的開發者往往會混淆這個概念。 切片和哈希表皆是引用類型,基礎數據和數組是值類型。
數組
數組是由相同類型元素的集合組成的數據結構,計算機會為數組分配一塊連續的內存來保存其中的元素,我們可以利用術組中元素的索引快速訪問特定元素。數組在初始化後大小、元素類型就無法改變。
數組初始化
arr1 := [3]int{1, 2, 3}
arr2 := [...]int{1, 2, 3}
切片
切片,即動態數組,其長度並不固定,我們可以向切片中追加元素,它會在容量不足時自動擴容。 引用傳遞操作
type slice struct {
// * 指向起始地址
ptr unsafe.Pointer
// * 切片長度(邏輯長度,存放元素個數)
len int
// * 切片容量(物理長度,分配多少空間)
cap int
}
// * 宣告切片,s是一個 nil 空指針,沒有完成內存分配
var s []int
// * 宣告切片長度、容量為8,初始值0
s := make([]int,8)
// * 宣告切片長度、容量為16,初始值0
s := make([]int,8,16)
// * 宣告切片並初始化,長度、容量為3
var s []int{0,1,5}
切片操作
截取操作
每一次截取切片都會創建新的slice header
s := []int{1,2,3,4,5,6}
// * [1,2,3]
s1 = s[:3]
// * [2,3]
s2 = s[1:3]
// * [1,2,3,4,5]
s3 = s[:len(s)-1]
引用操作
但是不會對原切片擴容
func TestSlice (t *testing.T) {
s := []int{0,1,2}
// * [0,1,2] -> [10,1,2]
ChangeSlice (s)
}
// * s1 創建 slice header,拷貝 s(ptr, len, cap)
func ChangeSlice (s1 []int) {
s1[0] = 10
// * 不影響原先 s 切片
s1 = append(s1,20)
}
追加元素
擴容時遵循如下機制:
- 預期新容量超過原容量的兩倍,直接取預期新容量
- 原容量小於 256,直接取原容量的兩倍作為新容量
- 原容量大於 256,在原容量 n 基礎上循環執行 n+=(n+3*256)/4 的操作,直到 n 大於等於預期新容量,並取 n 作為新容量
- 提醒 slice 並不是併發安全的數據結構,使用時注意併發安全
func TestSlice (t *testing.T) {
s := []int{0,1,2}
// * {0,1,2,10},擴容會生成新地址
s = append(s,10)
}
func TestInitSlice (t *testing.T) {
s := make([]int,0,5)
for i := 0; i < 5; i++ {
s = append(s,i)
}
// * [0,1,2,3,4]
}
func TestInitSlice (t *testing.T) {
s := make([]int,5)
for i := 0; i < 5; i++ {
s[i] = i
}
// * [0,1,2,3,4]
}
刪除元素
本質為截取切片
s := []int{0,1,2,3,4}
// * 刪除 idx 2 元素,[0,1,3,4],len 4,cap 5
s := append(s[:2],s[3:]...)
// * 刪除切片所有元素,len 0,cap 5
s := s[:0]
切片拷貝操作
// * s1/s2 新的 slice header(ptr, len, cap)拷貝,s2 len 少 1,兩個切片操作相同內存空間
s := []int{0,1,2,3,4}
s1 := s
s2 := s[1:]
// * 開闢新內存空間,拷貝元素到新的空間,兩個切片互相獨立
s := []int{0,1,2,3,4}
s1 := make ([]int{}, len(s))
copy (s1, s)
哈希表
map 是一種無序基於key-value的數據結構,Go 是引用類型,必須初始化才能使用。 make 用於 slice、map、channel 初始化
make 創建map
userinfo := make(map[string]string)
userinfo["name"] = "merry"
userinfo["age"] = "20"
make 創建map
programinfo := map[string]string{
"name": "merry",
"age": "20",
}
哈希表操作
查找、創建、更新、刪除
userinfo := make(map[string]string)
userinfo["name"] = "merry"
userinfo["age"] = "20"
v, ok := userinfo["age"]
delete(userinfo, "age")