Go基础编程:复合类型—切片slice

1. 概述

数组的长度在定义之后无法再次修改;数组是值类型,每次传递都将产生一份副本。显然这种数据结构无法完全满足开发者的真实需求。Go语言提供了数组切片(slice)来弥补数组的不足。

切片并不是数组或数组指针,它通过内部指针和相关属性引⽤数组⽚段,以实现变⻓⽅案

slice并不是真正意义上的动态数组,而是一个引用类型。slice总是指向一个底层array,slice的声明也可以像array一样,只是不需要长度。

这里写图片描述

2. 切片的创建

slice和数组的区别:声明数组时,方括号内写明了数组的长度或使用…自动计算长度,而声明slice时,方括号内没有任何字符。

    var s1 []int //声明切片和声明array一样,只是少了长度,此为空(nil)切片
    s2 := []int{}

    //make([]T, length, capacity) //capacity可以省略,则和length的值相同
    var s3 []int = make([]int, 0)
    s4 := make([]int, 0, 0)

    s5 := []int{1, 2, 3} //创建切片并初始化

3. 切片的操作

3.1 切片截取

操作含义
s[n]切片s中索引位置为n的项
s[:]从切片s的索引位置0到len(s)-1处所获得的切片
s[low:]从切片s的索引位置low到len(s)-1处所获得的切片
s[:high]从切片s的索引位置0到high处所获得的切片,len=high
s[low:high]从切片s的索引位置low到high处所获得的切片,len=high-low
s[low:high:max]从切片s的索引位置low到high处所获得的切片,len=high-low,cap=max-low
len(s)切片s的长度,总是<=casp(s)
cap(s)切片s的容量,总是>=len(s)

示例说明:

    array := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
操作结果lencap说明
array[:6:8][0 1 2 3 4 5]68省略 low
array[5:][5 6 7 8 9]55省略 high、 max
array[:3][0 1 2]310省略 high、 max
array[:][0 1 2 3 4 5 6 7 8 9]1010全部省略

3.2 切片和底层数组关系

    s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

    s1 := s[2:5]       //[2 3 4]
    s1[2] = 100        //修改切片某个元素改变底层数组
    fmt.Println(s1, s) //[2 3 100] [0 1 2 3 100 5 6 7 8 9]

    s2 := s1[2:6] // 新切片依旧指向原底层数组 [100 5 6 7]
    s2[3] = 200
    fmt.Println(s2) //[100 5 6 200]

    fmt.Println(s) //[0 1 2 3 100 5 6 200 8 9]

3.3 内建函数

3.3.1 append

append函数向 slice 尾部添加数据,返回新的 slice 对象:

    var s1 []int //创建nil切换
    //s1 := make([]int, 0)
    s1 = append(s1, 1)       //追加1个元素
    s1 = append(s1, 2, 3)    //追加2个元素
    s1 = append(s1, 4, 5, 6) //追加3个元素
    fmt.Println(s1)          //[1 2 3 4 5 6]

    s2 := make([]int, 5)
    s2 = append(s2, 6)
    fmt.Println(s2) //[0 0 0 0 0 6]

    s3 := []int{1, 2, 3}
    s3 = append(s3, 4, 5)
    fmt.Println(s3)//[1 2 3 4 5]

append函数会智能地底层数组的容量增长,一旦超过原底层数组容量,通常以2倍容量重新分配底层数组,并复制原来的数据:

func main() {
    s := make([]int, 0, 1)
    c := cap(s)
    for i := 0; i < 50; i++ {
        s = append(s, i)
        if n := cap(s); n > c {
            fmt.Printf("cap: %d -> %d\n", c, n)
            c = n
        }
    }
    /*
        cap: 1 -> 2
        cap: 2 -> 4
        cap: 4 -> 8
        cap: 8 -> 16
        cap: 16 -> 32
        cap: 32 -> 64
    */
}

3.3.2 copy

函数 copy 在两个 slice 间复制数据,复制⻓度以 len 小的为准,两个 slice 可指向同⼀底层数组。

    data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    s1 := data[8:]  //{8, 9}
    s2 := data[:5] //{0, 1, 2, 3, 4}
    copy(s2, s1)    // dst:s2, src:s1

    fmt.Println(s2)   //[8 9 2 3 4]
    fmt.Println(data) //[8 9 2 3 4 5 6 7 8 9]

4. 切片做函数参数

func test(s []int) { //切片做函数参数
    s[0] = -1
    fmt.Println("test : ")
    for i, v := range s {
        fmt.Printf("s[%d]=%d, ", i, v)
        //s[0]=-1, s[1]=1, s[2]=2, s[3]=3, s[4]=4, s[5]=5, s[6]=6, s[7]=7, s[8]=8, s[9]=9,
    }
    fmt.Println("\n")
}

func main() {
    slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    test(slice)

    fmt.Println("main : ")
    for i, v := range slice {
        fmt.Printf("slice[%d]=%d, ", i, v)
        //slice[0]=-1, slice[1]=1, slice[2]=2, slice[3]=3, slice[4]=4, slice[5]=5, slice[6]=6, slice[7]=7, slice[8]=8, slice[9]=9,
    }
    fmt.Println("\n")
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值