Golang 数据结构之 Slice (二)

前言

Golang 数据结构之 Slice (一)
上一篇文章写了Slice的基本数据结构,而且提到了Slice可以自动扩容,这篇文章就简单看看Slice是怎么样扩容的。

append函数

说扩容之前,不得不说一下 Slice 内置的 append 函数,这是一个用于向slice 追加元素的函数

func main(){
		var nums []int
		for i := 0; i < 10; i++ {
			nums = append(nums, i)
		}
		fmt.Printf("nums: %+v", nums)
	}

append 函数对于理解Slice 底层是如何进行工作的,有重要的意义。这是 builtin/builtin.go 中关于append func的说明,append 函数将元素附加到 Slice 的末尾。

// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
//	slice = append(slice, elem1, elem2)
//	slice = append(slice, anotherSlice...)
// As a special case, it is legal to append a string to a byte slice, like this:
//	slice = append([]byte("hello "), "world"...)
  • 如果它有空间足够,则重新划分目标以容纳新元素,即将元素附加在末尾;
  • 如果没有,将分配一个新的底层数组,将原来的元素复制过去,再附加;
  • append 返回更新后的切片。 因此需要将 append 的结果用输入的 slice 接收,这个情况后面会说到。

另外一个appendInt函数描述了这个过程

func appendInt(x []int, y int) []int {
    var z []int
    zlen := len(x) + 1
    if zlen <= cap(x) {
        z = x[:zlen]
    } else {
        zcap := zlen
        if zcap < 2*len(x) {
            zcap = 2 * len(x)
        }
        z = make([]int, zlen, zcap)
        copy(z, x) // 复制
    }
    z[len(x)] = y
    return z
}
  • 内置的 copy 函数将一个slice复制到另一个相同类型的 slice;
  • copy函数的第一个参数是要复制的目标slice,第二个参数是源slice;
  • 两个slice可以共享同一个底层数组,甚至有重叠也没有问题;
  • copy函数将返回成功复制的元素的个数。

扩容

通过在每次扩大数组时直接将长度翻倍从而避免了多次内存分配,也确保了添加单个元素操的平均时间是一个常数时间。也大大提高了内存的使用效率。

func main() {
	var nums []int
	for i := 0; i < 10; i++ {
		nums = append(nums, i)
		fmt.Printf("cap=%d\t%v\n", cap(nums), nums)
	}
}

在这里插入图片描述

  • 通常我们并不知道 append 调用是否导致了扩容,因此我们也不能确认新的slice和源slice是否引用的是相同的底层数组。

  • 同样,我们不能确认在源的slice上的操作是否会影响到新的slice。所以上面说的,通常是将append 返回的结果直接赋值给输入的 slice变 量

	nums = append(nums, i)

下一篇文章分析一下 growslice 函数的源码

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值