Slice切片
Slice 切片#
数组的缺点#
- 1. Go 中的数组是值类型,换句话说,如果你将一个数组赋值给另外一个数组,那么,实际上就是将整个数组拷贝一份
- 2. 如果 Go 中的数组作为函数的参数,那么实际传递的参数是一份数组的拷贝,而不是数组的指针。这个和 C 要区分开。因此,在 Go 中如果将数组作为函数的参数传递的话,那效率就肯定没有传递指针高了。
区分数组的声明和切片的声明方式#
当使用字面量来声明切片时,其语法与使用字面量声明数组非常相似。二者的区别是:如果在 [] 运算符里指定了一个值,那么创建的就是数组而不是切片。只有在 [] 中不指定值的时候,创建的才是切片。看下面的例子
为什么需要切片#
数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型 Slices 切片 (“动态数组”), 与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。切片中有两个概念:一是 len 长度,二是 cap 容量,长度是指已经被赋过值的最大下标 + 1,可通过内置函数 len () 获得。容量是指切片目前可容纳的最多元素个数,可通过内置函数 cap () 获得。切片是引用类型,因此在当传递切片时将引用同一指针,修改值将会影响其他的对象。
切片简介#
- 切片是可动态变化的序列,是对数组的引用,引用类型,遵循引用传递的机制
- slice 类型写作 [] T,T 是 slice 元素类型,var s1 [] int,s1 就是切片变量,空中括号是切片的典型标志
具体介绍#
切片之所以被称为切片,是因为创建一个新的切片,也就是把底层数组切出一部分。通过切片创建新切片的语法如下:
其中 i 表示从 slice 的第几个元素开始切,j 控制切片的长度(j-i),k 控制切片的容量(k-i),如果没有给定 k,则表示切到底层数组的最尾部。
slice[i:j]
slice[i:j:k]
下面是几种常见的简写形式:#
// 创建一个整型切片 其长度和容量都是 5 个元素
//对应的下标 0:10,1:20,2:30,3:40,4:50,
myNum := []int{10, 20, 30, 40, 50}
newNumTmp := myNum[1:4]
//i 表示从 slice 下标为 i 开始切,j 控制切片的长度
//[i:j] 表示 从下标为i开始切,新的切片元素个数是 j-i 个
//[:j] == [0:j]
//[i:] == [i:len()]
//标识从下标1开始切 切 4-1 个元素 所以结果是 [20 30 40]
newNumTmp1 := myNum[3:4]
// 表示从 slice 下标为 3 的元素开始 切 4-3 等于1个元素 所以结果是 [40]
newNumTmp2 := myNum[3:5]
// 表示从 slice 下标为 3 的元素开始 切 5-3 等于2个元素 所以结果是 [40 50]
newNumTmp3 := myNum[0:4]
// 表示从 slice 下标为 0 的元素开始 切 4-0 等于4个元素 所以结果是 [10 20 30 40]
newNumTmp4 := myNum[:4]
// 表示从 slice 下标为 0 的元素开始 切 4-0 等于4个元素 所以结果是 [10 20 30 40]
newNumTmp5 := myNum[2:]
// 表示从 slice 下标为 2 的元素开始 切 切片的长度 - 2 等于5 - 2 等于 3 个元素 所以结果是 [30 40 50]
newNumTmp6 := myNum[2:5]
// 表示从 slice 下标为 2 的元素开始 切 切片的长度 - 2 等于5 - 2 等于 3 个元素 所以结果是 [30 40 50]
简单案例#
//创建一个数组
var array1 [5]int = [...]int{11, 22, 33, 44, 55}
/*
创建切片,通过对数组的索引切片
s1 是切片名
array1[1:3]代表slice引用数组区间,索引1到索引3的值,注意取头不取尾,
*/
s1 := array1[1:4]
fmt.Printf("array1 = %v s1 = %v len(s1) = %v cap(s1) = %v \n",array1,s1,len(s1),cap(s1))
//结果
array1 = [11 22 33 44 55] s1 = [22 33 44] len(s1) = 3 cap(s1) = 4
切片原理#
- slice 是一个轻量级数据结构,提供访问数组子序列元素的功能。
- slice 由三个部分构成,指针、长度、容量
- 指针:指针指向 slice 第一个元素对应的数组元素的地址。
- 长度:slice 元素的数量,不得超过容量。
- 容器:slice 开始的位置到底层数据的结尾。
切片操作#
//创建数组data
array := [...]int{0, 1, 2, 3, 4, 5}
//切片s [2,3]
slice := array[2:4]
//切片读写操作目标是底层数组data,data的值会一起被修改
slice[0] += 100
slice[1] += 200
fmt.Printf("slice = %v array = %v",slice,array)
//运行结果
slice = [102 203] array = [0 1 102 203 4 5]
创建切片的方式#
- 1. 定义切片,然后引用已经创建好的数组,数组可见
//创建数组和切片的不同,数组中,中括号不能为空,必须是 ... 或者是具体数字(元素个数)
var s1 []int = []int{1, 2, 3, 4, 5}
var array1 = [...]int{11, 22, 33, 44}
fmt.Printf("array1 = %v s1 = %v 长度 = %v 容量 = %v \n",array1,s1,len(s1),cap(s1))
//返回值
array1 = [11 22 33 44] s1 = [1 2 3 4 5] 长度 = 5 容量 = 5
使用下标创建切片#
// 使用空字符串初始化第 10 个元素
myStr := []string{9: ""}
fmt.Println(len(myStr))
fmt.Println(helper.InterfaceHelperObject.ToString(myStr))
//打印的结果如下
10
["","","","","","","","","",""]
创建空切片#
var myNum []int
fmt.Println(myNum)
fmt.Println(nil)
fmt.Println(helper.InterfaceHelperObject.ToString(myNum))
//返回数据
[]
<nil>
null
- 2. 内置 make 函数创建切片,底层数组看不见,只能通过 slice 访问元素
内置make函数,参数(类型,len,cap),注意cap大于len,容量可以省略,默认等于长度
//如果cap不传默认容量就是长度
slice3 := make([]int, 10) 和 slice := make([]int, 10, 10) 一个意思
//简单案例
slice := make([]int, 10, 30)
slice[0] = 11
//如果 slice[10] = 11 或者 slice[11] = 11 都会报错,因为 下标范围是 0 - 9
//也就是下边必须小于 10 ,30代表 append 的时候最多到下边 29
// slice = append(slice, 400)
fmt.Printf("slice = %v",slice)
//打印
slice = [11 0 0 0 0 0 0 0 0 0]
本作品采用《CC 协议》,转载必须注明作者和本文链接