10-切片slice

97 阅读2分钟

切片

  • 一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容
  • 切片是一个引用类型,它的内部结构包含地址长度容量。切片一般用于快速地操作一块数据集合

格式: var name []T

package main
import (
    "fmt"
)

func main() {
    // 定义数组
    var intArr [6]int = [6]int{1, 2, 3, 4}
    // 切片 从索引1开始切到3结束 [1, 3)
    var slice []int = intArr[1: 3]// 写法1
    slice1 := intArr[1: 3]// 写法2

    fmt.Println(slice)// [2 3]
    fmt.Println(slice1)// [2 3]
    // 切片长度
    fmt.Println("切片长度", len(slice1))// 2
    // 获取切片容量: 容量一般是可以动态变化
    fmt.Println("获取切片容量", cap(slice1))// 5 
}

image.png

切片的截取

package main
import (
    "fmt"
)

func main() {
    // 定义数组
    var intArr [6]int = [6]int{1, 2, 3, 4, 5, 6}
    // 切片
    var slice1 = intArr[:3]// [0, 3) -> [1 2 3]
    var slice2 = intArr[1:]// [1, len(intArr)) -> [2 3 4 5 6 7] 
    var slice3 = intArr[1:4]// [1, 4) -> [2 3 4] 
    var slice4 = intArr[:]// [0, len(intArr)) -> [1 2 3 4 5 6]
    fmt.Println(slice1) 
    fmt.Println(slice2) 
    fmt.Println(slice3) 
    fmt.Println(slice4) 
}

image.png

切片的遍历

  • for循环
  • for-range循环
package main
import (
    "fmt"
)

func main() {
    var intArr = []int{1, 2, 3, 4}
    sum := 0;
    for i := 0;i <len(intArr); i++ {
        sum += intArr[i];
    }
    fmt.Println(sum)

    for i, value := range intArr {
        fmt.Println(i, value)
    }
}

image.png

切片的增/删/改/查

package main
import (
    "fmt"
)

func main() {
    var s1 = []int{1, 2 }
	
    // 动态添加 append函数
    s1 = append(s1, 100)
    s1 = append(s1, 200)
    fmt.Println(s1)

    // 删除指定的 append(s1[:i], s1[i+1:]...) 索引如:2
    s1 = append(s1[:2], s1[3:]...)
    fmt.Println(s1)// [1 2 200]

    // 修改
    s1[1] = 20
    fmt.Println(s1)// [1 20 200]

    // 查询
    fmt.Println(s1[1])// 20
}

image.png

切片的拷贝

  • 直接赋值的内存地址是同一块,修改一个另一个也会变化
  • 拷贝之前需要make([]T, len)分配一下对应的内存 -> 在使用copy(当前切片, 原始切片)
    • len >= 原切片长度全部copy,多了补默认值int -> 0
    • len < 原切片长度全部copy 拷贝len位
package main
import (
    "fmt"
)

func main() {
    var s1 = []int{1, 20, 200 }

    // copy拷贝 
    s2 := s1 // s1和s2是同一片内存地址
    s2[0] = 10
    fmt.Println(s1)// [10 20 200]
    fmt.Println(s2)// [10 20 200]

    // copy的时候需要make分配一下内存
    var s3 = make([]int, 4)
    copy(s3, s1)
    s3[0] = 50
    fmt.Println(s1)
    fmt.Println(s3)
}

image.png

append的底层逻辑

  1. 底层追加元素时对数组进行扩容,老数组扩容成新数组
  2. 创建一个新数组, 将老数组里面的值如: 1 2 3 复制到新数组中,在新数组中追加元素如: 4-> [1 2 3 4]
  3. append方法返回的底层数组是一个新的地址
  4. 一般会赋值给原来的切片
  5. 底层的新数组,不能直接维护,需要通过切片间接维护操作

...使用: 类似js扩展运算符的作用

package main
import (
    "fmt"
)

func main() {
    var s1 = []int{1, 20}
    s2 := []int{30, 40}
    s1 = append(s1, s2...)
    fmt.Println(s1)// [1 20 30 40]
}

make创建切片 make([]T, len, cap)

  • eg: 输出下面代码结果
package main
import (
    "fmt"
)

func main() {
    var a = make([]string, 5, 10)
    for i := 0; i < 10; i++ {
        a = append(a, fmt.Sprintf("%v", i))
    }
    fmt.Println(a, len(a))//["" "" "" "" "" 0 1 2 3 4 5 6 7 8 9]  15
}