首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么在Golang中创建一个片时会有一个容量参数

为什么在Golang中创建一个片时会有一个容量参数
EN

Stack Overflow用户
提问于 2019-02-20 08:42:34
回答 2查看 558关注 0票数 2

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

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

我认为这与内存管理有关,某种“知道如何分配内存中的片”,但我并不确切知道。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-02-20 08:45:20

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

我不知道你这么说是什么意思,但容量是不能超过的。切片可以被索引到它的长度(排他的),这不能超过容量,并且它们可以被重新分割到它的容量(包括在内)。

Spec:索引表达式:

表单a[x]的主要表达式 如果a不是地图:...the索引x在范围内如果是0 <= x < len(a),则为超出范围

规范:切片表达式:

...the主表达式:a[low : high] 对于数组或字符串,如果是0 <= low <= high <= len(a),则索引在范围内,否则它们超出范围。对于片,上索引界是片容量cap(a),而不是长度。

还包括:

...the主表达式:a[low : high : max] 如果是0 <= low <= high <= max <= cap(a),则指数在范围内,否则就超出了范围。

您可以为考虑未来增长的内置make()提供能力,因此,如果需要向其添加元素或需要重新分配它,则需要更少的分配。内置的append()只是重新分配您附加到的切片,如果它有足够的容量来处理额外的元素,但是如果它没有容纳新元素的空间,它就必须分配一个新的支持数组(并将现有的内容复制到它中)。append()将返回新的切片,该切片可能指向或不指向原始支持数组。

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

代码语言:javascript
运行
复制
fmt.Println("With 0 capacity")
s := make([]int, 0)
for i := 0; i < 10; i++ {
    s = append(s, i)
    fmt.Println(i, &s[0])
}

这一产出如下:

代码语言:javascript
运行
复制
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)时,以及在追加第一个元素(因为原始支持数组无法容纳任何元素)时,将分配一个新的支持数组。

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

代码语言:javascript
运行
复制
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])
}

现在的产出将是:

代码语言:javascript
运行
复制
With 10 capacity
0 0x44c030
1 0x44c030
2 0x44c030
3 0x44c030
4 0x44c030
5 0x44c030
6 0x44c030
7 0x44c030
8 0x44c030
9 0x44c030

如您所见,第一个元素的地址从未改变,这意味着后台没有发生新的支持数组分配。

围棋游乐场上试试这个例子。

票数 10
EN

Stack Overflow用户

发布于 2019-02-20 11:50:53

要增加片的容量,就必须创建一个新的、更大的片,并将原始片的内容复制到其中。

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

假设我们提前知道片的容量,那么就可以使用内置函数的容量参数来分配内存,而不是通过追加来动态增加片的容量,这并不是内存效率的问题。

所以在下面的例子中

代码语言:javascript
运行
复制
type Element struct {
    Number int
}

func main() {
    Max := 100000
    startTime := time.Now()

    // Capacity given
    elements1 := make([]Element, Max, Max)
    for i := 0; i < Max; i++ {
        elements1[i].Number = i
    }
    elapsedTime := time.Since(startTime)
    fmt.Println("Total Time Taken with Capacity in first place: ", elapsedTime)

    startTime = time.Now()
    // Capacity not given
    elements2 := make([]Element, 0)
    for i := 0; i < Max; i++ {
        elements2 = append(elements2, Element{Number: i})
    }
    elapsedTime = time.Since(startTime)
    fmt.Println("Total Time Taken without capacity: ", elapsedTime)
}

output

Total Time Taken with Capacity in first place:  121.084µs
Total Time Taken without capacity:  2.720059ms

首先构建具有容量的切片所花费的时间要比动态构建的时间要少。

因此,要回答您的问题,容量参数首先是为了更好的性能和内存效率。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54782079

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档