切片

什么是切片?

切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。

切片是一个引用类型,它的内部结构包含地址、长度和容量。切片一般用于快速地操作一块数据集合。

创建切片跟创建数组唯一的区别在于 Type 前的 "[]" 中是否有数字,为空,则代表切片,否则则代表数组。因为切片是长度可变的。

切片的本质

切片的本质就是对底层数组的封装,它包含了三个信息,底层数组的指针,切片的长度len()  和切片的容量 cap()

切片的声明

第一种方法

var slice1 []string
fmt.Println(slice1)
slice[0] = "嗯嗯嗯"  这种方法无法添加元素,
可以用append进行扩容
slice1 = append(slice1, "哈哈哈", "嘿嘿嘿", "啊啊啊")
fmt.Println(slice1, len(slice1))

第二种方法

声明并赋值

var slice2 = []string{"哈哈哈", "呵呵呵", "嘿嘿嘿"}
fmt.Println(slice2, len(slice2))

第三种方法,使用make函数

var slice3 = make([]string, 10, 10)
slice3[0] = "哈哈哈"
slice3[1] = "风风风"
fmt.Println(slice3, len(slice3))

第四种方法,基于数组创建切片

由于切片的底层就是一个数组,所以我们可以基于数组定义切片
a := [5]int{1, 2, 3, 4, 5}
b := a[:]
fmt.Printf("类型:%T,值是:%v", b, b)

第五种方法,基于切片再定义切片

除了基于数组得到切片,我们还可以通过切片得到切片
a := []string{"河北", "河南", "湖北", "湖南"}
b := a[1:]
fmt.Printf("a的类型:%T,b的类型:%T", a, b)

不同类型的数据的零值

关于nil的认识
当声明了一个变量,但是还没有赋值时,golang会自动给你的变量赋值一个默认的零值。下面是
每种类型对应的零值
 bool -> false
 number -> 0
 string -> ""
 pointers -> nil
 slices -> nil
 map -> nil
 channel -> nil
 func -> nil

 

切片的遍历

第一种:for range

var slice4 = []string{"哈哈","嘿嘿","嗯嗯","嗷嗷"}
for k, v := range slice4 {
    fmt.Println(k, v)
}

第二种:下标

var slice5 = []string{"哈哈", "嘿嘿", "嗯嗯", "啊啊"}
for i := 0; i < len(slice5); i++ {
    fmt.Println(slice4[i])
}

 

关于切片的长度和容量

切片拥有自己的长度和容量,我们使用len()函数来获取切片长度,cap()函数来获取切片的容量
切片的长度就是它所包含的元素个数
切片的容量就是从它的第一个元素开始数,到其底层数组元素末尾的个数

切片的操作

1. 扩容

//切片扩容,没法用下标的方式扩容,用append
var slice5 []int // 这种方式声明的切片,长度和容量都为0
slice5 = append(slice5, 11)
slice5 = append(slice5, 22)
fmt.Printf("长度:%v,容量:%v", len(slice5), cap(slice5))
# 长度:2,容量:2

2. append合并切片

append方法可以合并切片,注意:合并切片的时候最后一个元素要加...
sliceA := []string{"php", "java"}
sliceB := []string{"python", "nodejs"}
sliceB = append(sliceB, sliceA...) // 把sliceA合并到sliceB中
fmt.Println(sliceB)

3. 切片的扩容

var sliceA []int
for i := 0; i <= 10; i++ {
    sliceA = append(sliceA, i)
    fmt.Printf("长度:%v,容量:%v \n", len(sliceA), cap(sliceA))
}

4. 切片的复制

值类型:改变副本的时候,不影响变量本身的值
引用类型:改变副本的时候,会改变变量本身的值(slice,map,channel)
sliceA := []int{11, 22, 33}
sliceB := sliceA
sliceB[0] = 1000
fmt.Println(sliceA)
fmt.Println(sliceB)
# [1000 22 33]
# [1000 22 33]
# 可以看出改变副本sliceB的时候,sliceA也被改了

5. copy 复制切片

sliceA := []int{11, 22, 33, 44}
sliceB := make([]int, 4, 4)
copy(sliceB, sliceA) // sliceA复制给sliceB
fmt.Println(sliceA)
fmt.Println(sliceB)
sliceB[0] = 1000
fmt.Println(sliceA)
fmt.Println(sliceB)
// 修改sliceB的元素不会影响sliceA

6. 删除切片的元素

Go语言中并没有专门删除切片元素的方法,我们可以使用切片本身的特性来删除元素,代码:
a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
要删除索引为2的元素
a = append(a[:2], a[3:]...)
fmt.Println(a)

补充:修改字符串的字符

// 1. 如果字符串没有中文,转换为[]byte
s1 := "big"
byteStr := []byte(s1)
byteStr[0] = 'p'
fmt.Println(string(byteStr))

// 2.如果字符串有中文,转换为[]rune
s2 := "你好,世界"
runeStr := []rune(s2)
runeStr[0] = ''
fmt.Println(string(runeStr))
posted @ 2022-12-19 15:11  羊脂玉净瓶  阅读(286)  评论(0)    收藏  举报