Why use arrays instead of slices?

Issue

I have been reading up on Go, and got stumped thinking about this fundamental question.

In Go, it is quite clear that slices are more flexible, and can generally be used in place of arrays when you need a sequence of data.

Reading most of the documentation, they seem to be encouraging developers to just use slices instead of arrays. The impression I get feels like the creators could have simply designed arrays to be resize-able, and done without the entire slices section. In fact, such a design would have made the language even easier to understand, and perhaps even encouraged more idiomatic code.

So why did the creators allow arrays in the first place? When would arrays ever be used instead of slices? Is there ever a situation where the use of arrays over slices will be compelling?

When I consulted the official documentation (http://golang.org/doc/effective_go.html#arrays), the only useful part I found was:

Arrays are useful when planning the detailed layout of memory and
sometimes can help avoid allocation, but primarily they are a building block
for slices.

They went on to talk about how arrays are expensive as values, and how to simulate C-style behavior with pointer. Even then, they ended the array section with a clear recommendation:

But even this style isn’t idiomatic Go. Use slices instead.

So, what are some real examples of “planning the detailed layout of memory” or “help avoid allocation” that slices would be unsuited for?

Solution

As said by Akavall, arrays are hashable. That means they can be used as a key to a map.

They are also pass by value. Each time you pass it to a function or assign it to another variable it makes a complete copy of it.

They can be serialized by encoding/binary.

They also can be used to control memory layout. Since it is not a reference, when it is placed in a struct, it will allocate that much memory as part of the struct instead of putting the equivalent of a pointer there like a slice would.

Bottom line, don’t use an array unless you know what you are doing.


Hashable/serializable are all nice to have, but I’m just not sure if they are indeed that compelling to have

What would you do if you wanted to have a map of md5 hashes? Can’t use a byte slice so you would need to do something like this to get around the type system:

// 16 bytes
type hashableMd5 struct {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p byte}

Then create a serialization function for it. Hashable arrays mean that you can just call it a [16]byte.

Sounds like getting closer to C’s malloc, sizeof

Nope, that has nothing to do with malloc or sizeof. Those are to allocate memory and get the size of a variable.

However, CGo is another use case for this. The cgo command creates types that have the same memory layout as their corresponding C types. To do this, it sometimes needs to insert unnamed arrays for padding.

If problems can be solved with … nil/insignificant performance penalty using slices …

Arrays also prevent indirects making certain types of code faster. Of course this is such a minor optimization that this is insignificant in nearly all cases.

Answered By – Stephen Weinberg

Answer Checked By – Senaida (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.