关于个人对于slice 的部分理解

92 阅读4分钟

今天看到了一篇文章,其关于slice进行了基本的说明,其slice有三个变量,一个是cap,一个是len还有一个是数组的指针。分别对应的是slice 的可容纳长度,现有长度,以及首地址的指针。 但是对于不同的用法其值的变化会不同。

a := make([]int,4,5) fmt.Printf("a的cap为%d,a的len为%d,a为%d,a的地址为%p\n",cap(a),len(a),a,&a)

例如这行代码的作用就是构建一个长度为5,现有长度为4的一个slice切片,其默认值都是0。 同时如果我们make的时候没有第二个参数即没有说明cap的长度,默认为跟len一样长。 如果我们不是通过make构建的话 即使用var创建一个切片它默认的切片长度和现有长度都为0,也就是说cap==len==0;

slice还有一个特点!

当容量足够时,进行append操作直接修改其len并在a数组后进行追加即可

当容量不足时,进行append操作,会发生扩容,此时的数组地址发生变化,cap变为原来的2倍(不完全是2倍,可能会因为字节对齐的原因在2倍的基础上略有偏差); 例如下面这个代码

a := make([]int, 3, 4)
b := append(a,1)
fmt.Printf("a的cap为%d,a的len为%d,a为%d,a的地址为%p,a数组的地址为%p\n",cap(a),len(a),a,&a,&a[0])
fmt.Printf("b的cap为%d,b的len为%d,b为%d,b的地址为%p,b数组的地址为%p\n",cap(b),len(b),b,&b,&b[0])
a = append(a,2,3)
fmt.Printf("a的cap为%d,a的len为%d,a为%d,a的地址为%p,a数组的地址为%p\n",cap(a),len(a),a,&a,&a[0])
fmt.Printf("b的cap为%d,b的len为%d,b为%d,b的地址为%p,b数组的地址为%p\n",cap(b),len(b),b,&b,&b[0])

它的运行结果是

a的cap为4,a的len为3,a[0 0 0],a的地址为0x1400011e018,a数组的地址为0x1400012e020
b的cap为4,b的len为4,b[0 0 0 1],b的地址为0x1400011e030,b数组的地址为0x1400012e020
a的cap为8,a的len为5,a[0 0 0 2 3],a的地址为0x1400011e018,a数组的地址为0x14000124080
b的cap为4,b的len为4,b[0 0 0 1],b的地址为0x1400011e030,b数组的地址为0x1400012e020

我们可以发现当cap容量足够时,cap不会变 这个时候len会增长,但是 当cap不够的时候它会扩容,为原来的两倍,当然这个会有偏差,例如这个例子。

a := make([]int, 4)
fmt.Printf("a的cap为%d,a的len为%d,a为%d,a的地址为%p,a数组的地址为%p\n",cap(a),len(a),a,&a,&a[0])
a = append(a,1,2,3,4,5)
fmt.Printf("a的cap为%d,a的len为%d,a为%d,a的地址为%p,a数组的地址为%p\n",cap(a),len(a),a,&a,&a[0])

其结果为

a的cap为4,a的len为4,a[0 0 0 0],a的地址为0x14000114018,a数组的地址为0x14000124020
a的cap为10,a的len为9,a[0 0 0 0 1 2 3 4 5],a的地址为0x14000114018,a数组的地址为0x1400012a000

我们发现当我们append增长的超过了cap时,它增到的比两倍多了。但是不是整数倍扩容。 这就是slice很神奇的地方。 以上我个人对于那片文章的理解,大家如果相对其有更深入的了解可以查看这篇文章 go slice 实例分析 - 掘金 (juejin.cn) 这是原文章地址。