切片
1.为啥使用切片?
1数组的容量固定 不能自动拓展
2值传递 数组作为函数参数时,将整个数组值拷贝一份给形参
在GO语言当中,我们几乎可以在所有场景中使用切片替换数组使用
2.切片的本质:
切片并不是数组或数组指针,它通过内部指针和相关属性引⽤数组⽚段,以实现变⻓⽅案。
它是一种数据结构体
3.切片的使用
- 切片名称 [low:high:max] [:high:max] [low:] [:high]
- low:起始下标位置
- high:结束下标的位置
- len:high-low
- 容量:cap= max-low
截取数组 初始化切片且没有指定切片容量时候,切片容量跟随原数组
arr := [8]int{1,2,3,4,5,6,7,8}
s := arr[1:5:7] //[2 3 4 5]
fmt.Println(s)
fmt.Println(len(s)) //4
fmt.Println(cap(s)) //7
s2:=s[0:6]
fmt.Println(s2)
fmt.Println(len(s2)) //6
fmt.Println(cap(s2)) //6
切片截取
*操作* | *含义* |
---|---|
*s[n]* | 切片s中索引位置为n的项 |
*s[:]* | 从切片s的索引位置0到len(s)-1处所获得的切片 |
*s[low:]* | 从切片s的索引位置low到len(s)-1处所获得的切片 |
*s[:high]* | 从切片s的索引位置0到high处所获得的切片,len=high |
*s[low:high]* | 从切片s的索引位置low到high处所获得的切片,len=high-low |
*s[low : high : max]* | 从切片s的索引位置low到high处所获得的切片,len=high-low,cap=max-low |
*len(s)* | 切片s的长度,总是<=cap(s) |
*cap(s)* | 切片s的容量,总是>=len(s) |
截取可表示为s[low:high:max]。low:表示下标的起点。 high:表示下标的终点(左闭右开,不包括此下标)。
array := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
*操作* | *结果* | *len* | *cap* | *说明* |
---|---|---|---|---|
*array********[:6:8]* | [0 1 2 3 4 5] | 6 | 8 | 省略 low |
*array********[5:]* | [5 6 7 8 9] | 5 | 5 | 省略 high、 max |
*array********[:3]* | [0 1 2] | 3 | 10 | 省略 high、 max |
*array********[:]* | [0 1 2 3 4 5 6 7 8 9] | 10 | 10 | 全部省略 |
4.数组和切片的区别
1. 创建数组时 []指定数组的长度
2. 创建切片时,[]为空或者...
5.创建切片
- 自动推导类型创建slice
s1 := [] int {1, 2, 3, 4}
- 借助****make****创建 slice格式:make(切片类型,长度,容量)
s2 := make([]int, 5, 10)
- make时,没有指定容量,那么 长度==容量 slice := make([]int,长度)
s1 := [] int {1, 2, 3, 4}
fmt.Println("s1=", s1) //s1= [1 2 3 4]
s2 := make([]int, 5, 10)
s2[4] = 7 //s2= [0 0 0 0 7]
//s2[5] = 9 // 报错:panic: runtime error: index out of range
fmt.Println("s2=", s2)
fmt.Printf("len(s2)=%d, cap(s2)=%d\n", len(s2), cap(s2))
//len(s2)=5, cap(s2)=10
s3 := make([]int, 5) // make时,没指定容量,那么 长度 == 容量
s3[2] = 3
fmt.Println("s3=", s3) //s3= [0 0 3 0 0]
fmt.Printf("len(s2)=%d, cap(s2)=%d\n", len(s3), cap(s3))
//len(s2)=5, cap(s2)=5
6.切片的append函数
append() 函数可以向 slice 尾部添加数据,可以自动为切片扩容。常常会返回新的 slice 对象 append(切片对象,待追加元素) 向切片增加元素时,切片的容量会自动增长 1024一下是2倍数增长
var s1 []int //创建nil切片,或者:s1 := make([]int, 0)
s1 = append(s1, 1) //追加1个元素
s1 = append(s1, 2, 3) //追加2个元素
s1 = append(s1, 4, 5, 6) //追加3个元素
fmt.Println(s1) //[1 2 3 4 5 6]
s2 := make([]int, 5)
s2 = append(s2, 6)
fmt.Println(s2) //[0 0 0 0 0 6]
s3 := []int{1, 2, 3}
s3 = append(s3, 4, 5)
fmt.Println(s3) //[1 2 3 4 5]
7.切片做函数参数
切片作为函数参数时,传引用(就是传内存地址)。
func testFunc(s []int) { // 切片做函数参数
s[0] = -1 // 直接修改 main中的 slice
}
func main() {
slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(slice)
testFunc(slice) // 传引用[0 1 2 3 4 5 6 7 8 9]
fmt.Println(slice) //[-1 1 2 3 4 5 6 7 8 9]
}
Exer: 刪除空格
func DeleteNull(data []string) []string {
out := data[:0]
for _, str := range data {
if str != "" {
out = append(out, str)
}
}
return out
}
func DeleteNull2(data []string) []string {
i := 0
for _, str := range data {
if str != "" {
data[i] = str
i++
}
}
return data[:i]
}
func main() {
data := []string{"Fuck", "", "Fucking", "", "", "umama", "blue"}
data2 := DeleteNull(data)
data3 := DeleteNull2(data)
fmt.Println(data2)
fmt.Println(data3)
}
8.copy函数
函数 copy 在两个 slice 间复制数据,复制⻓度以 len 小的为准,两个 slice 指向同⼀底层数组。直接对应位置覆盖。copy(目标位置切片,源位置切片)
data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := data[8:] //{8, 9}
s2 := data[:5] //{0, 1, 2, 3, 4}
copy(s2, s1) // dst:s2, src:s1
fmt.Println(s2) //[8 9 2 3 4]
fmt.Println(data) //[8 9 2 3 4 5 6 7 8 9]