go语言之切片slice

1、切片的介绍

切片是对数组的抽象,是数组的视图。go语言中数组的长度是不可变的,但是切片的长度可以改变,切片可以追加元素,追加元素时,切片的容量可以会被增加。

2、申明切片

	var name []int
	var name1 = make([]int, 0)
	name2 := make([]int, 0)

一般也通过数组进行截取来获取切片,例如

package main

import "fmt"

func main() {
   arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}           //长度为7的数组
   fmt.Println(fmt.Sprintf("arr[2:6]=%d", arr[2:6])) //切片 2,3,4,5 左包右不包
   fmt.Println(fmt.Sprintf("arr[2:]=%d", arr[2:]))   //切片只给起点 2 3 4 5 6 7
   fmt.Println(fmt.Sprintf("arr[:6]=%d", arr[:6]))   //切片只给终点 0 1 2 3 4 5
   fmt.Println(fmt.Sprintf("arr[:]=%d", arr[:]))     //切片不给起点不给终点 代表所有 0 1 2 3 4 5 6 7

   s2 := arr[:]
   s2 = s2[:5]                               //切片可以被再次切片,称之为Reslice
   fmt.Println(fmt.Sprintf("s2[:5]=%d", s2)) //[0 1 2 3 4]
   s2 = s2[2:]                               //切片可以被再次切片,称之为Reslice
   fmt.Println(fmt.Sprintf("s2[2:]=%d", s2)) //[2 3 4]
}

3、切片的更改

更改了切片的数据,会导致底层数组的数据也更改了,因为切片是底层数组的视图。

package main

import "fmt"

func updateSlice(s []int) {
   s[0] = 100
}

func main() {
   arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} //长度为7的数组

   //切片是对数组的视图
   fmt.Println(fmt.Sprintf("未调用updateSlice之前的arr:%d", arr))
   s1 := arr[2:]
   fmt.Println(fmt.Sprintf("未调用updateSlice之前的s1:%d", s1))
   updateSlice(s1)
   fmt.Println(fmt.Sprintf("调用了updateSlice之后的s1:%d", s1))
   fmt.Println(fmt.Sprintf("调用了updateSlice之后的arr:%d", arr)) //改变了切片,底层数组也改变了

   fmt.Println("----------------------------------------------")
   fmt.Println(fmt.Sprintf("未调用updateSlice之前的arr:%d", arr))
   s2 := arr[:]
   fmt.Println(fmt.Sprintf("未调用updateSlice之前的s2:%d", s2))
   updateSlice(s2)
   fmt.Println(fmt.Sprintf("调用了updateSlice之后的s2:%d", s2))
   fmt.Println(fmt.Sprintf("调用了updateSlice之后的arr:%d", arr)) //改变了切片,底层数组也改变了
   fmt.Println("----------------------------------------------")
}

运行

image-20220312000533123

4、切片的底层原理

先看一个例子

package main

import "fmt"

func main() {
   arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}  //长度为7的数组
   fmt.Println(fmt.Sprintf("arr=:%d", arr)) //[0 1 2 3 4 5 6 7]
   s3 := arr[2:6]
   fmt.Println(fmt.Sprintf("s3=:%d", s3)) //[2 3 4 5]
   s4 := s3[3:5]
   fmt.Println(fmt.Sprintf("s4=:%d", s4)) //[5 6]
}

运行

image-20220312000829359

说明

S3为[2 3 4 5]很好理解,从下标为2的位置开始截取4个元素

可是为什么S4为[5 6]呢?

S4是S3从下标为3的位置开始截取2个元素,可是下标3以后就没有了元素

原来是因为切片是底层数组的视图,S3虽然显示是[2 3 4 5] 但是它可以视察到底层数组5以后是6和7两个元素,这也是为什么能S4能获取6的原因

image-20220312003002639

slice底层原理

image-20220312003236239

①slice由ptr和len以及cap组成

②ptr是指针,指向切片的第一个元素

③len是切片的长度,从ptr开始到结束的元素个数,当下标 超过这个长度后会报下标越界的错误

④cap表示切片的容量,表示共可以存多少个元素,当添加元素后,如果容量不够,会自动扩容

⑤切片可以向后扩展,不可以向前扩展,扩展可以超过len的值,上面的例子很好的说明了这个情况

解释完后,我们打印上面例子的长度和容量

image-20220312004101171

posted @ 2022-03-12 00:47  南风丶轻语  阅读(149)  评论(0编辑  收藏  举报