<Go>4 数组、切片和 map

本文最后更新于:2023年6月27日 上午

4 数组、切片和 map

4.1 数组

数组可以存放多个同一类型的数据。数组也是一种数据类型。

在 Go 中,数组也是值类型。默认情况下为值拷贝,新旧数组互不影响

数组在内存中是一段连续的空间。数组名指向该数组空间的首地址,也是数组第一个元素的地址。

数组各个元素的地址间隔依据数组类型决定。

Go 中不允许可变大小的数组,也不允许使用变量作为数组大小。如有需求,请使用切片

数组的定义:

var array [10]int										// 数组元素为零值
var array1 [3]int = [3]int{1, 2, 3}						// 声明时即初始化
var array2 = [3]int{1, 2, 3}							// 类型推导
var array3 = [...]int{1, 2, 3, 4}						// 数组大小推导
var array4 = [4]int{1: 1, 0: 2, 3: 3, 2: 4}				// 指定那些下标元素
var array5 = [...]int{1: 1, 0: 2, 3: 3, 7: 4}			// 此时类型为 int[8]

访问数组元素:

数组名[下标]

4.2 切片

slice 切片是 Go 中特有的数据类型。切片的使用类似数组

切片是数组的引用,因此切片是引用类型。进行值传递时,遵守引用传递机制

切片的长度可变,因此切片是可以动态变化的数组

#切片的定义:

var s []int							// 声明一个切片
s1 := array4[1:3]					// 该切片引用数组 array4 [1,3) 范围的数据
s2 := make([]int, 4, 10)			// 使用 make 函数获得 长度4 容量10 的切片
s3 := make([]int, 5)				// 该切片容量、长度都是 5
s4 := array4[2:]					// 相当于 array4[2:len(array4)]
s5 := array4[:4]					// 相当于 array4[0:4]
s6 := array4[:]						// 相当于 array4[0:len(array4)]

切片声明后还不能使用,因为其为空。必须让其引用数组,或使用 make 方法产生切片空间后才能使用。

切片可以继续切片

#切片常用函数:

  • len(v) int:返回切片的长度(包含的元素数量)

  • cap(v) int:返回切片的容量(能包含的最大元素数量)

  • make(Type, IntegerType) Type:分配并初始化一个指定长度的切片

    make(Type, IntegerType, IntegerType) Type:返回一个指定长度、容量的切片

    通过 make 方式创建的切片,其对应数组由 make 函数底层维护,对外不可见。

  • append(slice []Type, ele Type...) slice:对切片进行动态追加。

    容量不足的场合会扩容。返回追加完毕后的新的切片

    Go 底层会创建新的数组,并将原有元素以 值拷贝 方式拷贝到新的数组。之后,返回一个引用新数组的新切片

    也就是说,切片进行 append 后,新的切片会失去对原有数组的引用

    也能追加一个切片:

    s = append(s, s...)				// 表示将 s 的全部元素追加到 s 后
  • copy(s []Type, o []Type):将 o 的数据拷贝(值拷贝)到 s。

    期间,s 的容量不变。s 容量更大时,多余位置保留原样。s 容量更小时,其余元素不保存。

#string 与 slice 的关系

因为 string 底层是 byte 数组,因此 string 也能进行切片处理

字符串是不可变的。不能通过下标直接改变 string 的字符。可以通过切片实现修改需求

想要改变字符串时,先将字符串转换成 []byte 或 []rune。修改后重新转换成字符串:

str := "刻晴刻晴刻晴刻晴"
s := []rune(str)[6:]
s = append(s, []rune("晴~~")...)
s[3] = '★'
str = string(s)								// 刻晴晴★~

4.3 map

map(映射)是 key-value 数据结构,又称字段或关联数组

key 可以是 slice、map、function 外的类型(这些类型不能使用 == 判断)。通常使用 int 或 string 做 key

#map 的定义:

var m map[string]int 					// key 是 string,value 是 int
m2 := make(map[string]int, 10)
m3 := map[int]string{
    0: "刻晴",
    1: "胡桃",
    2: "甘雨",
}

map 的声明时不分配内存,需要 make 后才能使用

#map 的 CRUD:

m["刻晴"] = 100					// 增加、修改 k-v
delete(m, "刻晴")					// 按照 key 删除 k-v
val, find := m["甘雨"]			// val 为查找到的值,find 为是否找到
for k, v := range m {				// 使用 for-range 进行遍历
    fmt.Println(k, " - ", v)
}

map 的 key 不能重复,value 可以重复。其 key - value 是无序存放的

要将 map 的 key 排序,只有先将所有 key 取出,再将取出的 key 排序,最后按照顺序取出那些值

#使用细节

  • map 是引用类型,遵守引用传递的机制
  • map 的容量达到后,会自动扩容
  • map 的 value 也常用 struct 类型,更适合管理复杂数据

<Go>4 数组、切片和 map
https://i-melody.github.io/2022/06/11/Go/4 数组、切片和 map/
作者
Melody
发布于
2022年6月11日
许可协议