1.说明
1)其本身并不是数组,它指向底层的数组
2)作为变长数组的替代方案,可以关联底层数组的局部或全部
3)为引用类型
4)可以直接创建或从底层数组获取生成
5)使用len()获取元素个数,cap()获取容量
6)一般使用make()创建
7)如果多个slice指向相同底层数组,其中一个的值改变会影响全部
8)切片本身没有数据,是对数组底层的一个view
2.创建:
make([]T, len, cap)
其中cap可以省略,则容量和len的值相同
len表示存数的元素个数,cap表示容量
代码实例:直接var s []int形式
package main
import "fmt"
func main() {
var s []int //没有元素则切片是空的
for i := 0; i < 100; i++ {
s = append(s, i)
}
fmt.Println(s)
}
输出:
API server listening at: 127.0.0.1:33537
[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99]
使用make创建:
package main
import "fmt"
func main() {
s := make([]int, 10)
for i := 0; i < 10; i++ {
s[i] = i
}
fmt.Println(s)
}
输出:
API server listening at: 127.0.0.1:21778
[0 1 2 3 4 5 6 7 8 9]
3.方法
1)Reslice
Reslice时所有以呗slice的切片为准
所有不可以超过呗slice的切片的容量cap()值
索引越界不会导致底层数组的重新分配而是引发错误
2)Append
可以在slice尾部追加元素
可以将一个slice追加在另一个slice尾部
如果最终长度为超过主机到slice的容量则返回原始slice
如果超过追加道德slice 的容量则将重新分配数组并拷贝原始数据
3)Copy
4.代码实例
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println("arr[2:6]:", arr[2:6])
fmt.Println("arr[:6]:", arr[:6])
fmt.Println("arr[2:]:", arr[2:])
fmt.Println("arr[:]:", arr[:])
}
输出:
API server listening at: 127.0.0.1:37693
arr[2:6]: [2 3 4 5]
arr[:6]: [0 1 2 3 4 5]
arr[2:]: [2 3 4 5 6 7 8 9]
arr[:]: [0 1 2 3 4 5 6 7 8 9]
上述代码中:
arr[2:6]从数组中取值是第2号元素到第5号元素,不包括6号
arr[:6]从头到第5号元素,不包括6号
arr[2:]从2号元素到结尾,包括2号元素
arr[:]获取所有元素
实例二
package main
import "fmt"
//参数中数组不加长度,这个就是切片
func updateSlice(s []int) {
s[0] = 999
}
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := arr[2:]
fmt.Println("s1:", s1)
s2 := arr[:]
fmt.Println("s2:", s2)
fmt.Println("after updateSlice(s1)")
updateSlice(s1)
fmt.Println(s1)
fmt.Println(arr)
fmt.Println("after updateSlice(s2)")
updateSlice(s2)
fmt.Println(s2)
fmt.Println(arr)
}
API server listening at: 127.0.0.1:19977
s1: [2 3 4 5 6 7 8 9]
s2: [0 1 2 3 4 5 6 7 8 9]
after updateSlice(s1)
[999 3 4 5 6 7 8 9]
[0 1 999 3 4 5 6 7 8 9]
after updateSlice(s2)
[999 1 999 3 4 5 6 7 8 9]
[999 1 999 3 4 5 6 7 8 9]
这段代码中updateSlice完成了对数组的数据更新
切片还有一种操作叫做reslice
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s := arr[:]
fmt.Println(s)
s = s[:5]
fmt.Println(s)
s = s[2:]
fmt.Println(s)
}
输出:
API server listening at: 127.0.0.1:3798
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4]
[2 3 4]
5.扩展
1)实例说明
看下面一段代码执行结果是多少:
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6
fmt.Println(s1)
s2 := s1[3:5]
fmt.Println(s2)
}
输出:
API server listening at: 127.0.0.1:43832
[2 3 4 5]
[5 6]
上述代码S的值是2,3,4,5但是s2是s1的切片,为什么取值不是s1里面的内容呢,显然5和6已经超出了范围。请看下图:
有底层数组向上一次是数组arr的内容是0,1,2,3,4,5,6,7那么s1作为arr的切片取值下标是2--6也就是说:
s1[0] = 2
s1[1] = 3
s1[2] = 4
s1[3] = 5
s1[4] = 6
s1[5] = 7
s2是s1的切片,取值是s1的3--5下标,对应到数组arr里面就是arr[5]--arr[6]两个元素
所以s2的元素值就是:
s2[0] = 5
s2[1] = 6
s2[2] = 7
2)底层实现
如下图所示slice内部三个元素
切片扩展有两个规则:
1)slice可以向后扩展,不可以向前扩展
2)s[i]不可以超越len(s),向后扩展不可以超越底层数组cap(s)
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6]
fmt.Println(s1)
fmt.Println(len(s1))
fmt.Println(cap(s1))
s2 := s1[3:5]
fmt.Println(s2)
fmt.Println(len(s2))
fmt.Println(cap(s2))
}
输出:
API server listening at: 127.0.0.1:21562
[2 3 4 5]
4
6
[5 6]
2
3
6.向切片增加元素
规则:
1)添加元素时如果超越cap,系统会重新分配更大的底层数组
2)由于值传递的关系,必须接收append的返回值(原因就是因为可能超越cap,这时分配的是新的底层数组)
看下面一段代码,通过append向切片内部增加元素
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6]
fmt.Println("s1 = ", s1)
s2 := s1[3:5]
fmt.Println("s2 = ", s2)
s3 := append(s2, 10)
s4 := append(s3, 11)
s5 := append(s4, 12)
fmt.Println("s3, s4, s5 = ", s3, s4, s5)
fmt.Println("arr = ", arr)
}
输出:
API server listening at: 127.0.0.1:18118
s1 = [2 3 4 5]
s2 = [5 6]
s3, s4, s5 = [5 6 10] [5 6 10 11] [5 6 10 11 12]
arr = [0 1 2 3 4 5 6 10]
上述代码显示s4和s5已经超越了arr所以这哥底层数组已经不是之前的arr了是一个新的arr
下面代码通过打印len和cap观察切片的长度和容量是如何扩展增加的,cap是倍数扩展的
package main
import "fmt"
func printSlice(s []int) {
fmt.Println("len(s) = cap(s) = ", len(s), cap(s))
}
func main() {
var s []int //没有元素则切片是空的,不会崩溃
for i := 0; i < 10; i++ {
printSlice(s)
s = append(s, i)
}
fmt.Println(s)
}
输出:
API server listening at: 127.0.0.1:25704
len(s) = cap(s) = 0 0
len(s) = cap(s) = 1 1
len(s) = cap(s) = 2 2
len(s) = cap(s) = 3 4
len(s) = cap(s) = 4 4
len(s) = cap(s) = 5 8
len(s) = cap(s) = 6 8
len(s) = cap(s) = 7 8
len(s) = cap(s) = 8 8
len(s) = cap(s) = 9 16
[0 1 2 3 4 5 6 7 8 9]
7.拷贝删除操作
package main
import "fmt"
func main() {
s1 := []int{2, 4, 6, 8}
fmt.Println("s1 = ", s1)
s2 := make([]int, 16)
fmt.Println("s2 = ", s2)
copy(s2, s1) //拷贝s1到s2
fmt.Println("s2 = ", s2)
s2 = append(s2[:3], s2[4:]...) //删除8
fmt.Println("s2 = ", s2) //打印出来可以看到8这个元素被删除了整个切片的长度小了一个
//删除头元素操作
front := s2[0] //取出来查看头元素
s2 = s2[1:] //删除头元素
fmt.Println("front = ", front)
fmt.Println("s2 = ", s2)
//删除尾元素操作
tail := s2[len(s2)-1] //取出来查看尾元素
s2 = s2[:len(s2)-1] //删除尾元素
fmt.Println("tail = ", tail)
fmt.Println("s2 = ", s2)
}
输出:
API server listening at: 127.0.0.1:47314
s1 = [2 4 6 8]
s2 = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
s2 = [2 4 6 8 0 0 0 0 0 0 0 0 0 0 0 0]
s2 = [2 4 6 0 0 0 0 0 0 0 0 0 0 0 0]
front = 2
s2 = [4 6 0 0 0 0 0 0 0 0 0 0 0 0]
tail = 0
s2 = [4 6 0 0 0 0 0 0 0 0 0 0 0]
|
请发表评论