How to implement resizable arrays in Go

Go

Go Problem Overview


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

Go Solutions


Solution 1 - Go

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.

Solution 2 - 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.

Solution 3 - Go

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

Solution 4 - Go

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
  }
}

Solution 5 - Go

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

append() Documentation here

Solution 6 - Go

Hi we can simply do this in two ways

type mytype struct {
  a, b int
}

Just do like this

  1. Without append

__

a := []mytype{mytype{1, 2}, mytype{3, 4}, mytype{4, 5}}

2. 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.

Solution 7 - Go

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser181351View Question on Stackoverflow
Solution 1 - Gocthom06View Answer on Stackoverflow
Solution 2 - Gouser418324View Answer on Stackoverflow
Solution 3 - GoJesseView Answer on Stackoverflow
Solution 4 - Gouser414731View Answer on Stackoverflow
Solution 5 - GoAshutosh ChamoliView Answer on Stackoverflow
Solution 6 - Goamku91View Answer on Stackoverflow
Solution 7 - GoRashid ObaidiView Answer on Stackoverflow