在Golang中创建切片时,为什么确切地存在CAPACITY参数 [英] Why exactly is there a CAPACITY parameter when creating a slice in Golang

查看:70
本文介绍了在Golang中创建切片时,为什么确切地存在CAPACITY参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个非常简单的问题:

This is a pretty straightforward question:

如果可以超过Golang中某个切片的容量,为什么首先要有一个容量参数?

If the capacity of a slice in Golang can be exceeded, why is there a capacity parameter in the first place?

我认为这与内存管理有关,即某种知道在内存中分配切片的位置",但我不完全知道.

I reckon this has to do with the memory management, some kind of "knowing where to allocate the slice in memory" but I don't know exactly.

推荐答案

如果可以超过Golang中某个切片的容量,为什么首先要有一个容量参数?

If the capacity of a slice in Golang can be exceeded, why is there a capacity parameter in the first place?

我不知道您的意思是什么,但是容量不能超过.可以在不超过容量的长度(不包括其长度)的范围内对切片进行索引,并且可以根据其容量(包括)进行重新切片.

I don't know what you mean by this, but the capacity can't be exceeded. Slices can be indexed up to its length (exclusive) which can't exceed the capacity, and they can be re-sliced up to its capacity (inclusive).

规范:索引表达式:

形式为 a [x]

如果 a 不是地图:...如果 0< = x<len(a),否则超出范围

If a is not a map: ...the index x is in range if 0 <= x < len(a), otherwise it is out of range

规范:切片表达式:

...主要表达式: a [low:high]

对于数组或字符串,如果 0< =低< =高< = len(a),则索引在范围内 ,否则它们为超出范围.对于切片,索引的上限是切片容量 cap(a)而不是长度.

For arrays or strings, the indices are in range if 0 <= low <= high <= len(a), otherwise they are out of range. For slices, the upper index bound is the slice capacity cap(a) rather than the length.

还有:

...主要表达式: a [low:high:max]

如果 0< =低< =高< =最大值< = cap(a),则索引在范围内,否则它们是超出范围.

The indices are in range if 0 <= low <= high <= max <= cap(a), otherwise they are out of range.

您可以为内置 make() 考虑到未来的增长,因此,如果您需要向其添加元素或需要对其进行切片,则将需要较少的分配.内置的 append() 只是对您附加到的切片进行切片如果它具有足够的容量来容纳其他元素,但是如果它没有空间容纳新元素,则必须分配一个新的后备数组(并将现有内容复制到其中). append()将返回可能指向也可能不指向原始后备数组的新切片.

You may provide the capacity to the builtin make() thinking of future growth, so fewer allocations will be needed should you need to append elements to it or should you need to reslice it. The builtin append() just reslices the slice you append to if it has enough capacity for the additional elements, but it has to allocate a new backing array (and copy the existing contents into it) if it has no room for the new elements. append() will return the new slice which may or may not point to the original backing array.

让我们看一个例子.让我们创建一个长度和容量为0的切片,并向其附加10个元素.为了查看何时发生新的重新分配,我们还打印了其第一个元素(第0个元素)的地址:

Let's see an example. Let's create a slice with 0 length and capacity, and append 10 elements to it. And to see when a new reallocation happens, we also print the address of its first element (the 0th element):

fmt.Println("With 0 capacity")
s := make([]int, 0)
for i := 0; i < 10; i++ {
    s = append(s, i)
    fmt.Println(i, &s[0])
}

这将输出:

With 0 capacity
0 0x416030
1 0x416030
2 0x416040
3 0x416040
4 0x452000
5 0x452000
6 0x452000
7 0x452000
8 0x434080
9 0x434080

如您所见,当我们附加第三个( i = 2 ),第五个( i = 4 )和第九个元素( i = 8 ),以及附加第一个元素时(因为原始后备数组无法容纳任何元素).

As you can see, a new backing array is allocated when we appended the third (i=2), fifth (i=4) and ninth elements (i=8), and also when we appended the first element (as the original backing array could not hold any elements).

现在,当我们创建长度为0但容量为10的初始切片时,让我们重复上面的示例:

Now let's repeat the above example when we create the initial slice with again length = 0 but with capacity = 10:

fmt.Println("With 10 capacity")
s = make([]int, 0, 10)
for i := 0; i < 10; i++ {
    s = append(s, i)
    fmt.Println(i, &s[0])
}

现在的输出将是:

With 10 capacity
0 0x44c030
1 0x44c030
2 0x44c030
3 0x44c030
4 0x44c030
5 0x44c030
6 0x44c030
7 0x44c030
8 0x44c030
9 0x44c030

如您所见,第一个元素的地址从未更改,这意味着在后台没有新的后备数组分配发生.

As you can see, the address of the first element never changed, which means there were no new backing array allocations happening in the background.

游乐场上尝试该示例.

这篇关于在Golang中创建切片时,为什么确切地存在CAPACITY参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆