06-golang切片

1、什么是切片

在学习切片前,我们存储相同类型的数据集合只能用数组。但是数组有一个弊端,就是长度固定,无法扩容。这时候,切片就出现了。切片(slice)是对数组的一个连续片段的引用,所以切片是一种引用类型。切片基于数组做了封装,长度可变,支持动态扩容。切片的底层数据结构包含3个元素:指针长度容量

2、切片的声明初始化

下面代码是切片声明和简单初始化的方法,但是实际开发中很少这样做,一般使用make关键字来创建切片。

// 声明切片的基本语法
var 变量名 []元素类型

func main() {
    var a []string  //声明一个字符串型的切片
    var b = []int{} //声明一个int型的切片并初始化
    var c = []int{1, 2} //声明一个int型的切片并初始化

    fmt.Println(a)  // []
    fmt.Println(b)  // []
    fmt.Println(c)  // [1 2]
}

3、切片表达式

切片是对数组的一个连续片段的引用,golang中提供了切片表达式,我们可以用切片表达式从已有数组中获得切片。

切片表达式基本语法:

数组名[low:high:max]
  • low:表示所要切片的对象左索引(从切片对象的哪个地方开始切,包含low索引)
  • high:表示所要切片的对象右索引(切片要切到哪里,不包含high索引)
  • max:设置切片容量的相关参数,最后切片的容量为max -low。max是一个可选参数,如果不设置max,则可以认为max的默认值为数组的长度
简单示例
func main() {
    a := [5]int{1,2,3,4,5}
    s := a[1:4:4]
        // 左包含,右不包含。实际切的是底层数组的索引1,2,3
    fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s)) // s:[2 3 4] len(s):3 cap(s):3
}

需要注意的是数组越界的问题:参数要满足0 <= low <= high <= max <= len()

4、使用make创建切片

使用make关键字创建切片是最常用的方式。

基本语法:

slice := make([]type, len, cap)
  • type:元素类型
  • len:切片的长度(实际元素数量)
  • cap:切片的容量

使用make创建切片时,长度和容量是必要的参数。如果两个参数都填的话,则长度和容量都按相应的参数设置。如果只填一个参数的话,则长度和容量的值都为该参数。切片中元素的默认值则为对应类型的零值。

简单示例
func main() {
   s1 := make([]int, 2, 3)
   // 切片数据:[0 0],切片长度:2,切片容量:3
   fmt.Printf("切片数据:%v,切片长度:%v,切片容量:%v \n", s1, len(s1), cap(s1))
   s2 := make([]int, 3)
   // 切片数据:[0 0 0],切片长度:3,切片容量:3
   fmt.Printf("切片数据:%v,切片长度:%v,切片容量:%v \n", s2, len(s2), cap(s2))
}

5、切片的底层数据结构

我们知道切片是对数组的一个连续片段的引用。它包含了3个元素:指向底层数组片段的指针,切片长度(切片中元素的数量),切片容量(切片指向的片段所能容纳元素数量)

img

简单示例

现在有一个数组a := [8]int{0, 1, 2, 3, 4, 5, 6, 7},切片s1 := a[:5],相应示意图如下:

img

切片s2 := a[3:6],相应示意图如下:

img

6、切片相关操作方法

6.1 切片的拷贝

切片是一种引用类型,所以切片的拷贝分为深拷贝和浅拷贝。深拷贝指的是将切片的数据复制到另一块内存中,赋值给新变量,两个变量对切片的操作。浅拷贝指的是将切片的引用地址赋值给新变量。

深拷贝

深拷贝指的是将切片的数据复制到另一块内存中。这样,两个切片的操作互不影响。

func main() {
   s1 := []int{1, 2, 3, 4, 5}
   s2 := make([]int, 5, 5)
   // 复制切片s1的底层数组给s2
   copy(s2, s1)
   fmt.Println(s1) // [1 2 3 4 5]
   fmt.Println(s2) // [1 2 3 4 5]
   s2[1] = 10
   fmt.Println(s1) // [1 2 3 4 5]
   fmt.Println(s2) // [1 10 3 4 5]
}
浅拷贝

浅拷贝指的是将切片变量赋值给另一变量,两个变量共享切片底层数组,操作切片的话会互相影响。

func main() {
   a := [5]int{1, 2, 3, 4, 5}
   s1 := a[1:4]
   s2 := s1
   fmt.Println(s1) // [2 3 4]
   fmt.Println(s2) // [2 3 4]
   s2[1] = 10
   fmt.Println(s1) // [2 10 4]
   fmt.Println(s2) // [2 10 4]
}

6.2 切片遍历

切片的遍历和数组一样,支持索引遍历和for range遍历。

func main() {
    s := []int{1, 3, 5}
    // 索引遍历
    for i := 0; i < len(s); i++ {
        fmt.Println(i, s[i])
    }
    // for range遍历
    for index, value := range s {
        fmt.Println(index, value)
    }
}

6.3 往切片中添加元素

golang中内置函数append()可以动态地往切片中添加元素,支持添加一个或多个元素,同时支持动态添加切片。

func main() {
    var s []int
    s = append(s, 1)
    fmt.Println(s)  // [1]
    s = append(s, 2, 3) // [1 2 3]
    fmt.Println(s)
    s1 := make([]int, 2, 2)
    s1[0] = 4
    s1[1] = 5
    s = append(s, s1...)
    fmt.Println(s)  // [1 2 3 4 5]
}

6.4 从切片中删除元素

func main() {
   s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
   // 删除元素5
   s = append(s[:4], s[5:]...)
   for _, value := range s {
      fmt.Println(value)
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值