如何在Go中实现可resize的数组

我来自一个C + +的背景,我习惯于使用这个std::vector类。 让我们假设我想要这些dynamic数组:

 type a struct { b int c string } 

这样做的标准方式是什么?

一个片段将是非常有用的

使用append()内build

例:

 type mytype struct { a, b int } func main() { a := []mytype{mytype{1, 2}, mytype{3, 4}} a = append(a, mytype{5, 6}) } 

关于追加的更多信息,请参阅规范 。

Go Slice包含三个元素:数据,长度和容量。

 s := make([]int, 0, 10) 

variabless是长度为0,容量为10的整数的一部分。内置的len()和cap()函数允许您获取片的长度和容量:

 len(s) == 0 cap(s) == 10 

要增加切片的长度,只需重新切片即可:

 s = s[0:5] // len(s) == 5 // cap(s) == 10 

为了减less长度,你可以采取一个子片:

 s = s[0:1] // len(s) == 1 

有一些简短的方法来调用make():

 a := make([]int, 10) // len(a) == cap(a) == 10 b := make([]int) // len(b) == cap(b) == 0 

这一切都很好,但是如果你需要增加超出容量的分片长度呢? 要做到这一点,你需要分配一个新的切片,并将旧的切片的内容复制到新的切片。 (“复制”function是另一种内置function。)

 t := make([]int, len(s), 20) copy(t, s) 

Effective Go文档将此示例稍微进一步实现了一个Append函数,该函数将一个切片添加到另一个切片,并在必要时调整其大小。

切片由数组支持; 当您创build()一个特定容量的分片时,将在后台分配该容量的数组。 切片有效地成为该数组的“智能指针”。 如果将该片(或该片的子片)传递给另一个函数,则将其作为指向该相同数组的指针传递。 这使得创build子分片非常便宜 – 这是分配昂贵的后备数组。

Go标准库包含许多容器包(例如vector),无需手动pipe理切片。 使用切片来提高速度,为了方便,使用更复杂的容器类。 (说,我仍然使用切片的大部分事情。)

你可能想知道为什么你需要去解决这个问题。 毕竟,很多语言提供dynamicresize的数组作为原语。 其原因与Go的哲学有关。 语言devise者不会认为你的程序知道什么是合适的分配策略; 相反,他们给你的工具,你需要build立自己的数据结构。

这种做法的惯用方式已经改变。 内置的append()函数的添加意味着您可以像这样扩展切片:

 type a struct { b int c string } func main(){ var mySlice []a mySlice = append(mySlice,a{5,"pizza"}) } 

如果有空间,Append()会将给定的项目追加到切片上,如果切片不够大,则延长切片。

有关append()的更多信息,请访问http://golang.org/doc/go_spec.html#Appending_and_copying_slices

你也可以做一个切片。 这是一个知道当前长度的数组。 并可以有一个单独的电stream长度和最大容量。 请注意,为初始大小和容量传递的值不一定是常量,因此您可以创build一个函数,根据其参数构build并返回不同长度的片。

最重要的是,slice [] Int可以像数组一样被索引,并且在以这种方式使用时将返回int。

缺点是它不会自动增长超过其规定的能力。 Effective Go就是你如何去处理重新分配的一个例子。

代码将是

 type mytype struct { a, b int } func main() { sl := make([]mytype, 10, 50) //slice of 10 items, max capacity 50 these do not have to be constant expressions. sl[0] = mytype{1,2} //... for i, value := range sl { // ... do stuff with value } }