初识切片
根本应用
在go语言中个别不应用数组,大多都是应用切片(slice),看一个切片的示例
arr := [...]int{0,1,2,3,4,5,6,7,8}
s := arr[2:6]
这里定的s就是切片,上边的arr是一个数组,这里s的后果是[2,3,4,5](取arr中3到5这个区间的数据,是左闭右开的)
切片还有很多的用法,如下:
arr := [...]int{0,1,2,3,4,5,6,7,8}
fmt.Println("arr[2:6] = ", arr[2:6])
fmt.Println("arr[:6] = ", arr[:6])
fmt.Println("arr[2:] = ", arr[2:6])
fmt.Println("arr[:] = ", arr[:])
输入后果:
arr[2:6] = [2 3 4 5]
arr[:6] = [0 1 2 3 4 5]
arr[2:] = [2 3 4 5]
arr[:] = [0 1 2 3 4 5 6 7 8]
像这种方括号中([])加个冒号(:)的数据结构,都能够看做是切片(slice)。当然还有很多其它的申明办法
切片是对数组的view
咱们晓得在go中,数组是一个值类型,而切片是一个援用类型,切片是对数组的视图(view),可能不太好了解,看下边的代码
func updateSlice(s []int) {
s[0] = 520
}
func main() {
arr := [...]int{0,1,2,3,4,5,6,7,8}
s1 := arr[2:]
fmt.Println("s1更新之前")
fmt.Println("s1 = ", s1)
fmt.Println("arr = ", arr)
fmt.Println("更新切片s1")
updateSlice(s1)
fmt.Println("更新之后,s1和arr的值")
fmt.Println(s1)
fmt.Println(arr)
}
输入后果:
s1更新之前
s1 = [2 3 4 5 6 7 8]
arr = [0 1 2 3 4 5 6 7 8]
更新切片s1
更新之后,s1和arr的值
[520 3 4 5 6 7 8]
[0 1 520 3 4 5 6 7 8]
因为s1(切片)是对arr(数组)的视图(view),所以当s1中的值被扭转之后,数组中的值也产生了扭转(扭转的是s1中下标为0的元素,对应的是数组arr中下标为2的元素)
对切片进行切片操作
func learnSlice1() {
arr := [...]int{0,1,2,3,4,5,6,7,8}
s1 := arr[2:6]
s2 := s1[1:]
fmt.Println("s1 = ", s1)
fmt.Println("s2 = ", s2)
}
输入后果:
s1 = [2 3 4 5]
s2 = [3 4 5]
s2是对切片s1又进行了一次切片
深度了解切片
间接看一个示例
func learnSlice2() {
arr := [...]int{0,1,2,3,4,5,6,7,8}
s1 := arr[2:6]
s2 := s1[3:5]
fmt.Println("s1 = ", s1)
fmt.Println("s2 = ", s2)
}
s1的打印后果,咱们必定晓得,然而这里的s2打印后果是什么?
咱们晓得s1 = [2,3,4,5],s2是对s1取下标是3到5这个区间的数据,也就是s1[3]、s1[4]。然而能够看到s1的下标最大是s[3],那这里s1[3:5]会报错吗?
答案是不会报错,能够看一下打印的后果,而后再解释为什么
s1 = [2 3 4 5]
s2 = [5 6] //s1[3]、s1[4]
能够看到s2中的那个6就不在s1里边,如果咱们尝试间接打印s1[4]会报错。然而打印s2这个切片,就会失常打印出后果,那到底这个6是如何取出来的?
上边有说切片(slice)是对数组(array)的视图(view),那这个底层是什么样的,如何view的?
上边给出的根底数组arr是[0,1,2,3,4,5,6,7,8],而后s1 := arr[2:6],取到的就是[2,3,4,5],这四个数字映射到s1的下标就是0、1、2、3,s1里边因为是对底层数组arr的view,它的下标不是到3就完结了,它还有4、5的,然而间接通过s1[4]或s1[5]是取不到的,然而s1还是晓得它里边有4和5这两个下标的,因为s1是晓得底层的数组的
而后,s2 := s1[3:5],取到的就是s1中3,4这两个下标的值。s2的下标就是0、1、2(2其实是看不见的)。从底层数组的角度s1[3]、s1[4]的值就是5和6
切片外部实现
切片中首先有一个ptr指针,它指向slice开始的那个元素。有一个len,标记的是切片的长度,咱们应用下标的形式对切片取值的时候,最大只能取到下标为len-1的值,如果大于或等于len,就会报错。而后它里边还有一个值cap,它代表的是整个数组从ptr指向的地位开始到完结的长度
切片它能够向后扩大,然而不能够向后扩大。比方s1:=arr[2:6],s1最前边只能看到2,前边的0、1下标对应的值是看不到的
切片的下标不能够超过len(s),向后扩大不能够超过底层数组cap(s)
看一波示例
func learnSlice2() {
arr := [...]int{0,1,2,3,4,5,6,7,8}
s1 := arr[2:6]
s2 := s1[3:5]
fmt.Printf("s1 = %v, len(s1) = %d, cap(s1) = %d", s1, len(s1), cap(s1))
fmt.Println()
fmt.Printf("s2 = %v, len(s2) = %d, cap(s2) = %d", s2, len(s2), cap(s2))
}
输入后果
s1 = [2 3 4 5], len(s1) = 4, cap(s1) = 7
s2 = [5 6], len(s2) = 2, cap(s2) = 4
发表回复