切片的基本介绍
在不确定个数的多少的情况下,我就不能使用固定长度的数组了
1.切片的英文slice
2.切片是数组的一个引用,因此切片是引用数据类型,在进行传递时,遵守引用传递的机制;
3.切片的使用和数组类似,遍历切片,访问切片的元素和求切片长度len(slice) 都一样;
4.切片的长度是可以变化的,因此切片是一个可以动态变化的数组;
5.切片定义的基本语法:
var 切片名 []类型
示例:var a []int
切片在内存中的形式:(重要)
1.切片底层的数据结构可以理解成是一个结构体struct(ptr,len,cap)
2.输出切片和切片的引用地址;
切片的使用:
三种方式:
第一种:定义一个切片,然后让切片去引用一个已经创建好的数组;
第二种:通过make来创建切片;
基本语法:
var 切片名 []type = make([], len, [cap])
参数说明:type:数据类型,len:大小,cap:指定切片容量,可选
示例:
var slice_1 []int = make([]int, 4, 20) // 需要使用 make
// 输出 [0 0 0 0] 4 20
fmt.Println(slice_1, len(slice_1), cap(slice_1))
slice_1[2] = 20
slice_1[0] = 10
fmt.Println(slice_1) // [10 0 20 0]
使用make 创建的话,对应数组在底层只能通过slice 来访问和修改,对外不可见,区别于第一种方式,第一种方式可以通过数组也可以通过切片来访问;
第三种方式:var stringslice []string = []string{"tom", "jack", "marry"}
示例:
var stringslice []string = []string{"tom", "jack", "marry"}
fmt.Println(stringslice, len(stringslice), cap(stringslice)) // [tom jack marry] 3 3
方式一和方式二之间的区别:
1.方式一,是直接引用数组,这个数组是事先存在的,程序员是可见的;
2.方式二,是通过make来创建切片,make也会创建一个数组,是由切片在底层进行维护,程序员是看不见的;
切片的遍历:和数组进本一样没有什么特别注意的地方;
第一种:常规的方式;
第二种:for-range:
切片注意的事项和细节说明:
1.切片初始化时,var slice = arr[startindex:endindex]
说明:从arr数组下标为startindex, 取到下标为endindex的元素 不含 arr[endindex];
2.切片初始化时,任然不能越界,范围在 [0-len(arr)] 之间,但是可以动态增长;
var slice = arr[0:end] 可以简写 var slice = arr[:end]
var slice = arr[start:len(arr)] 可以简写:var slice = arr[start:]
var slice = arr[0:len(arr)] 可以简写:var slice = arr[:]
3.cap是一个内置函数,用于统计切片的容量,即最大可以存放多少个元素;
4.切片定义完后,还不能使用,因为本身是一个空的,需要让其引用到一个数组,或者make一个空间供切片使用;
5. 切片可以继续切片;
6.用append内置函数,可以对切片进行动态追加;
底层原理分析:
切片append操作的本质就是对数组扩容;
go底层会创建一个新的数组newArr
将slice原来包含的元素拷贝到新的数组newArr
slice重新引用到newArr
注意newArr是在底层来维护的,程序员不可见;
7.切片拷贝的操作;
copy[para1, para2] --> para1 和para2 都是切片类型;不管para1 和 para2 的长度只赋值对应位置的数值;切片是引用类型,所以在传递时,遵守引用传递机制;
string和slice:
1.string在底层是一个byte数组,因此string可以进行切片处理;
2.string和切片在内存的形式一样,都是引用数组,但是不能通过 str[0] = 'z' , 因为str是不可变的;
3.如果想修改字符串中的字符,可以先转成 []byte 切片,改完后再转为字符串;(可以处理英文和数字,汉字会乱码)
如果想解决中文乱码问题可以通过 转成 []rune 切片即可,因为[]rune 是按字符处理,兼容汉字;
示例:
str_1 := "hello@atguigu"
byte_arr := []rune(str_1)
// byte_arr[0] = 'g' // str_1== gello@atguigu
byte_arr[0] = '北' // str_1== 北ello@atguigu
str_1 = string(byte_arr)
fmt.Println("str_1==", str_1)