go切片(slice)

切片是对数组的一个连续片段的引用,所以切片是一个引用类型。切片 本身不拥有任何数据,它们只是对现有数组的引用,每个切片值都会将数组作为其底层的数据结构。slice 的语法和数组很像,只是没有固定长度而已。

创建切片

使用 []Type 可以创建一个带有 Type 类型元素的切片。

// 声明整型切片
var numList []int

// 声明一个空切片
var numListEmpty = []int{}

你也可以使用 make 函数构造一个切片,格式为 make([]Type, size, cap)

numList := make([]int, 3, 5)

当然,我们可以通过对数组进行片段截取创建一个切片。

arr := [5]string{"Go语言极简一本通", "Go语言微服务架构核心22讲", "从0到Go语言微服务架构师", "微服务", "分布式"}
var s1 = arr[1:4]
fmt.Println(arr) // [Go语言极简一本通 Go语言微服务架构核心22讲 从0到Go语言微服务架构师 微服务 分布式]
fmt.Println(s1)  // [Go语言微服务架构核心22讲 从0到Go语言微服务架构师 微服务]

切片的长度和容量

一个 slice 由三个部分构成:指针长度容量 。指针指向第一个 slice 元素对应的底层数组元素的地址,要注意的是 slice 的第一个元素并不一定就是数组的第一个元素。长度对应 slice 中元素的数目;长度不能超过容量,容量一般是从 slice 的开始位置到底层数据的结尾位置。简单的讲,容量就是从创建切片索引开始的底层数组中的元素个数,而长度是切片中的元素个数。

内置的 lencap 函数分别返回 slice 的长度和容量。

s := make([]string, 3, 5)
fmt.Println(len(s)) // 3
fmt.Println(cap(s)) // 5

如果切片操作超出上限将导致一个 panic 异常。

s := make([]int, 3, 5)
fmt.Println(s[10]) //panic: runtime error: index out of range [10] with length 3

Tips:

  • 由于 slice 是引用类型,所以你不对它进行赋值的话,它的默认值是 nil
var numList []int
fmt.Println(numList == nil) // true
  • 切片之间不能比较,因此我们不能使用 == 操作符来判断两个 slice 是否含有全部相等元素。特别注意,如果你需要测试一个 slice 是否是空的,使用 len(s) == 0 来判断,而不应该用 s == nil 来判断。

切片元素的修改

切片自己不拥有任何数据。它只是底层数组的一种表示。对切片所做的任何修改都会反映在底层数组中。

func modifySlice() {
	var arr = [...]string{"Go语言极简一本通", "Go语言微服务架构核心22讲", "从0到Go语言微服务架构师"}
	s := arr[:] //[0:len(arr)]
	fmt.Println(arr) //[Go语言极简一本通 Go语言微服务架构核心22讲 从0到Go语言微服务架构师]
	fmt.Println(s) //[Go语言极简一本通 Go语言微服务架构核心22讲 从0到Go语言微服务架构师]

	s[0] = "Go语言"
	fmt.Println(arr) //[Go语言 Go语言微服务架构核心22讲 从0到Go语言微服务架构师]
	fmt.Println(s) //[Go语言 Go语言微服务架构核心22讲 从0到Go语言微服务架构师]
}

这里的 arr[:] 没有填入起始值和结束值,默认就是 0len(arr)

追加切片元素

使用 append 可以将新元素追加到切片上。append 函数的定义是 func append(slice []Type, elems ...Type) []Type 。其中 elems ...Type 在函数定义中表示该函数接受参数 elems 的个数是可变的。这些类型的函数被称为可变函数。

  func appendSliceData() {
	s := []string{"Go语言极简一本通"}
	fmt.Println(s)
	fmt.Println(cap(s))

	s = append(s, "Go语言微服务架构核心22讲")
	fmt.Println(s)
	fmt.Println(cap(s))

	s = append(s, "从0到Go语言微服务架构师", "分布式")
	fmt.Println(s)
	fmt.Println(cap(s))

	s = append(s, []string{"微服务", "分布式锁"}...)
	fmt.Println(s)
	fmt.Println(cap(s))
}

当新的元素被添加到切片时,如果容量不足,会创建一个新的数组。现有数组的元素被复制到这个新数组中,并返回新的引用。现在新切片的容量是旧切片的两倍。

多维切片

类似于数组,切片也可以有多个维度。

func mSlice() {
	numList := [][]string{
		{"1", "Go语言极简一本通"},
		{"2", "Go语言微服务架构核心22讲"},
		{"3", "从0到Go语言微服务架构师"},
	}
	fmt.Println(numList)
}
posted @ 2023-07-06 21:09  Bre-eZe  阅读(26)  评论(0)    收藏  举报