美文网首页go学习
Go 切片(slice)

Go 切片(slice)

作者: 星垂平野阔 | 来源:发表于2017-09-29 10:18 被阅读39次

    Go中,数组的长度是不可变的,但是Go提供了一种灵活的内置类型:切片(也称为动态数组)。

    切片的长度不固定,可以追加元素,也可以扩容。

    slice 的本质

    slice是引用类型,是一个指向数组的指针。

    在内存中,一个slice是一个结构体:

    struct Slice
    {
        byte* array;    // actual data
        uintgo  len;    // number of elements
        uintgo  cap;    /// allocated number of elements
    }
    

    所以,一个slice是一个包含三个域的结构体:指向slice中第一个元素的指针,slice的长度,slice的容量。

    slice的长度是slice中元素的个数,slice的容量是slice中最多能有的元素的个数。

    因此长度是下标操作的上界,如x[i]中 i 必须小于长度。容量是分割操作的上界,如x[i:j]中 j 不能大于容量。

    如下图:

    定义切片

    var s1 []int    // 声明一个未指定大小的数组来定义切片
    var s2 []int = make([]int, len)  // 使用make() 来创建切片
    s3 := make([]int, len)   // 同上
    s4 := make([]int, len, cap)  // 也可以指定容量。
    

    切片未初始化之前默认为 nil,长度为 0 。

    内置函数 len() 和 cap() 提过了获取切片长度和容量的方法。

    切片初始化和截取

    s1 := []int{1, 2, 3} // 直接初始化,其 cap = len = 3
    
    arr := [...]int{1, 3, 5, 7, 9, 11}  // arr 是一个数组
    s2 := arr[:]   // 切片s2 是数组arr的引用
    s3 := arr[2:5]  // s3 = [5, 7, 9]
    s3 := arr[2:]   // s3 = [5 7 9 11]  缺省endIndex时,就直到arr的最后一个元素
    s3 := arr[:3]   // s2 = [1, 2, 5]   缺省startIndex时,就从arr的第一个元素开始
    
    s4 := s3[startIndex:endIndex]  // 用切片s3 初始化 s4,但它们只是不同的结构体,指向了同一片内存区,共享底层数据
    

    切片追加元素

    内置函数 append() 可以向切片追加新元素。

    s1 = append(s1, 4)     // s1 = [1 2 3 4]
    s1 = append(s1, 5, 6)  // s1 = [1 2 3 4 5 6]
    
    

    对 slice 进行 append 操作时,可能会造成 slice 自动扩容。其扩容时的规则是:

    • 如果新的大小是当前大小的2倍以上,则大小增长为新大小
    • 否则循环一下操作:如果当前大小小于1024,按每次2倍增长,否则每次按当前大小的 1/4 增长。直达增长的大小超过或等于新大小。

    我们通常不知道 append 调用是否导致了内存的重新分配,因此我们不能确认新的slice和原始的slice是否引用的是相同的底层数组空间。同样,我们不能确认在原先的slice上的操作会不会影响到新的 slice,因此,通常是将 append 返回的结果直接复制给输入的 slice 变量, 即 s = append(s, r) 。

    手动扩容

    s5 := make([]int, len(s3), (cap(s3))*2)  // 创建切片s5 是 s3 的两倍容量
    copy(s5, s3) // 拷贝 s3 的内容到 s5
    

    slice作为函数参数

    向函数传递 slice 将允许在函数内部修改底层数组的元素。

    其他

    • 不能使用 == 来判断两个slice 是给含有全部相同元素
    • slice 唯一合法的比较是 和 nil 比较。
    • 判断 slice 是否为空,使用 len(s) == 0 , 而不是 s == nil

    相关文章

      网友评论

        本文标题:Go 切片(slice)

        本文链接:https://www.haomeiwen.com/subject/obobextx.html