【问题标题】:Is there any better way to handle slices of variable size?有没有更好的方法来处理可变大小的切片?
【发布时间】:2014-09-16 11:03:44
【问题描述】:

请看下面的代码

names := make([]string, 0, 100)
names = append(names, "Jack")
names = append(names, "Jacob")
// adding many names in here

考虑到这样的情况:我会从其他地方得到这些名字,在此之前我不知道它的大小。所以我需要一个动态数组来包含这些名称。上面的代码是我想出的方法。我想知道是否有更优雅的方式来做到这一点。

如果我这样初始化

names := make([]string, 100, 200)
// then I use append in here
// I would get first 100 elements as empty, the append start at index 101.

我想这会浪费很多内存。 我对静态编程语言完全陌生,所以如果这篇文章中有任何错误的概念,请指出。

【问题讨论】:

    标签: arrays go slice


    【解决方案1】:

    只需声明类型,然后将附加的切片分配给它:

    package main
    
    import "fmt"
    
    func main() {
        var names []string
        names = append(names, "foo")
        names = append(names, "bar")
        fmt.Println(names)
    }
    

    产量:

    >> [foo bar]
    

    如果您对它的机制感兴趣,这里有一个不错的blog post

    【讨论】:

    • 如果您更喜欢:= 的外观,您可以使用names := []string{} 作为几乎但不完全等效的方式。 (在当前的编译器上,:= 版本从一开始就离开了names != nil,而var 版本则没有。)
    【解决方案2】:

    坚持你正在做的事情。 100 不会阻止切片拥有更多的 100 个元素

    names := make([]string, 0, 100)
    names = append(names, "Jack")
    names = append(names, "Jacob")
    

    如果您对元素数量有粗略估计,并且始终使用 append 将元素添加到切片中,我强烈建议您设置切片的容量。您不必担心超出您的估计,因为 append 将创建新数组以适应添加的元素。

    names := make([]string)
    

    上述情况你的数组容量为0,追加会导致底层数组被一次又一次地创建。这将对性能产生影响。你应该避免这种情况。如果您担心在内存中占用更多空间,您可以考虑创建指向类型的指针切片

    objList := make([]*MyStructType, 0, 100)
    

    【讨论】:

    • @Gnani:您声称“您的数组的容量为 0 每次追加都会导致底层数组被一次又一次地创建”是错误的,它在摊销的常数时间内分配:append complexity。跨度>
    • @peterSO 我的错,感谢您指出。我知道,在某种程度上,go 不会。我想说一遍又一遍。我认为删除“每个”将使陈述正确。
    【解决方案3】:

    您可以考虑在容量之外设置一个初始长度,而不是“0”(100,意味着最多可以添加 100 个元素)。

    见“Arrays, slices (and strings): The mechanics of 'append'

    分配。

    我们可以使用新的内置函数来分配一个更大的数组,然后对结果进行切片,但使用 make 内置函数会更简单。
    它一次分配一个新数组并创建一个切片头来描述它。 make 函数接受三个参数:切片的类型、初始长度和容量,即 make 分配用于保存切片数据的数组的长度

    我们的想法是避免append() 不得不过早增长切片,尤其是如果您知道您将收到至少 n 个元素。

    【讨论】:

    • 不错的帖子,之前没仔细看,我真的应该赶上。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 2012-02-01
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多