英文:
How to implement resizable arrays in Go
问题
我来自C++背景,习惯使用std::vector
类来处理这类情况。
假设我想要一个动态数组来存储这些:
type a struct {
b int
c string
}
如何以标准的方式实现这个需求?
提供一个代码片段将非常有帮助
英文:
I come from a C++ background and I'm used to using the std::vector
class for things like this.
Lets assume I want a dynamic array of these:
type a struct {
b int
c string
}
What is the standard way of doing this?
A snippet would be very useful
答案1
得分: 102
使用append()
内置函数
示例:
type mytype struct {
a, b int
}
func main() {
a := []mytype{mytype{1, 2}, mytype{3, 4}}
a = append(a, mytype{5, 6})
}
有关append
的更多信息,请参考规范。
英文:
Use the append()
builtin
Example:
type mytype struct {
a, b int
}
func main() {
a := []mytype{mytype{1, 2}, mytype{3, 4}}
a = append(a, mytype{5, 6})
}
Refer to the spec for more info on append.
答案2
得分: 76
一个Go切片包含三个元素:数据、长度和容量。
s := make([]int, 0, 10)
变量s是一个长度为0、容量为10的int切片。内置的len()和cap()函数允许您获取切片的长度和容量:
len(s) == 0
cap(s) == 10
要增加切片的长度,只需重新切片:
s = s[0:5]
// len(s) == 5
// cap(s) == 10
要减少长度,可以使用子切片:
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
这些都很好,但是如果您需要将切片的长度增加到超过其容量,该怎么办?为此,您需要分配一个新的切片,并将旧切片的内容复制到新切片中。(函数"copy"是另一个内置函数。)
t := make([]int, len(s), 20)
copy(t, s)
Effective Go文档进一步介绍了这个例子,实现了一个Append函数,它将一个切片追加到另一个切片中,并在需要时调整大小。
切片由数组支持;当您使用make()创建一个具有特定容量的切片时,背后会分配一个具有该容量的数组。切片实际上成为指向该数组的“智能指针”。如果您将该切片(或该切片的子切片)传递给另一个函数,它将作为指向同一数组的指针传递。这使得子切片的创建非常廉价 - 昂贵的是分配后备数组。
Go标准库包括许多容器包 - 例如vector - 它们消除了手动管理切片的需要。使用切片来提高速度,使用更复杂的容器类来提供方便。(话虽如此,我仍然大多数情况下使用切片。)
您可能想知道为什么需要这么麻烦。毕竟,很多语言提供了动态调整大小的数组作为原语。这是由于Go的哲学。语言设计者不假设他们知道您的程序的适当分配策略;相反,他们为您提供了构建自己的数据结构所需的工具。
英文:
A Go Slice contains three elements: data, length, and capacity.
s := make([]int, 0, 10)
The variable s is a slice of ints with a length of 0 and a capacity of 10. The built-in len() and cap() functions allow you to get the length and capacity of a slice:
len(s) == 0
cap(s) == 10
To increase the length of a slice, simply re-slice:
s = s[0:5]
// len(s) == 5
// cap(s) == 10
To decrease the length, you can take a sub-slice:
s = s[0:1]
// len(s) == 1
There are some shorter ways to invoke make():
a := make([]int, 10)
// len(a) == cap(a) == 10
b := make([]int)
// len(b) == cap(b) == 0
That's all well and good, but what if you need to increase the length of a slice beyond its capacity? To do that, you need to allocate a new slice and copy the contents of the old slice to the new one. (The function "copy" is another built-in.)
t := make([]int, len(s), 20)
copy(t, s)
The Effective Go document takes this example a bit further, implementing an Append function that appends one slice to another, resizing it if necessary.
Slices are backed by arrays; when you make() a slice of a specific capacity, an array of that capacity is allocated in the background. The slice effectively becomes a "smart pointer" to that array. If you pass that slice (or a subslice of that slice) to another function, it is passed as a pointer to that same array. This makes sub-slices very cheap to create - it's the allocation of the backing array that is expensive.
The Go standard library includes a number of container packages - vector, for instance - that eliminate the need to manually manage slices. Use slices for speed, and more elaborate container classes for convenience. (Saying that, I still use slices for most things.)
You may be wondering why you need to go to all this trouble. After all, a lot of languages provide dynamically resized arrays as primitives. The reason for this is tied to Go's philosophy. The language designers don't presume to know what the appropriate allocation policy is for your program; instead they give you the tools you need to build your own data structures.
答案3
得分: 30
这个的惯用方式已经改变了。
内置的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
英文:
The idiomatic way to do this has changed.
The addition of the built-in append() function means that you can extend a slice like so:
type a struct {
b int
c string
}
func main(){
var mySlice []a
mySlice = append(mySlice,a{5,"pizza"})
}
Append() will append the given item to the slice if there is room or extend the slice if it's not bigger enough.
More information about append() is here http://golang.org/doc/go_spec.html#Appending_and_copying_slices
答案4
得分: 5
对于append()
内置函数的一个更简单的示例
friends := []string{"Adam"}
friends = append(friends, "Rahul") // 添加一个朋友或一个字符串
friends = append(friends, "Angelica", "Rashi") // 添加多个朋友或多个字符串
英文:
For a Simpler Example of the append()
builtin
friends := []string{"Adam"}
friends = append(friends, "Rahul") // Add one friend or one string
friends = append(friends, "Angelica", "Rashi") // Add multiple friends or multiple strings
答案5
得分: 2
你可能也可以使用切片来满足需求。切片是一个数组,它知道自己的当前长度,并且可以有单独的当前长度和最大容量。请注意,传递的初始大小和容量的值不必是常量,因此您可以创建一个根据参数构建并返回不同长度切片的函数。
优点是,切片[]Int可以像数组一样进行索引,并在这种方式下返回整数。
缺点是,它不会自动扩展超出其声明的容量。Effective Go中有一个示例,展示了如何处理重新分配。
代码如下:
type mytype struct {
a, b int
}
func main() {
sl := make([]mytype, 10, 50) //切片有10个项,最大容量为50,这些值不必是常量表达式。
sl[0] = mytype{1,2}
//...
for i, value := range sl {
// ... 处理value
}
}
英文:
you might also be able to make do with a slice. which is an array that knows its current length. And can have a separate current length and maximum capacity. Note the values passed for initial size and capacity do not have to be constants so you can create a function which builds and returns slices of different lengths based on its parameters.
The up side is that a slice []Int can just be indexed like an array, and will return ints when used in this way.
The downside is that it will not automatically grow byound its stated capacity. Effective Go has an example of how you would go about handling reallocation.
the code would be
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
}
}
答案6
得分: 0
嗨,我们可以用两种方法来简单地完成这个任务。
type mytype struct {
a, b int
}
就像这样做
- 不使用append函数
__
a := []mytype{mytype{1, 2}, mytype{3, 4}, mytype{4, 5}}
- 使用append函数
__
a:= append([]mytype{}, mytype{1, 2}, mytype{3, 4}, mytype{4, 5})
可以添加任意数量的元素。第一种方法是一个简单的方式来完成这个任务。希望这对你有帮助。
英文:
Hi we can simply do this in two ways
type mytype struct {
a, b int
}
Just do like this
- Without append
__
a := []mytype{mytype{1, 2}, mytype{3, 4}, mytype{4, 5}}
- With append
__
a:= append([]mytype{}, mytype{1, 2}, mytype{3, 4}, mytype{4, 5})
Add as much as you want. First one is an easy way to do this. Hope this will help you.
答案7
得分: 0
如果你想在Go中拥有一个动态列表,那么你必须使用切片。
你可以在这里了解更多信息:
https://blog.golang.org/slices-intro
一些示例:
https://tour.golang.org/moretypes/7
https://gobyexample.com/slices
英文:
If you want to have a dynamic List in Go then you have to use Slice
you can learn more about it here:
https://blog.golang.org/slices-intro
Some Examples:
https://tour.golang.org/moretypes/7
https://gobyexample.com/slices
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论