Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map of structs vs array of structs in Go

Tags:

slice

struct

go

map

Let's say I have a simple struct a with a string property b:

type A struct {
    B string
}

The following code using an array of A types:

testArray := []A{A{}}
testArray[0].B = "test1"
fmt.Println(testArray[0].B)

Will print out "test1" as expected.

But this code that seems equally simple:

testMap := make(map[string]A)
testMap["key"] = A{}
testMap["key"].B = "test2"
fmt.Println(testMap["key"].B)

Will not print out "test2" but instead will result in the following error:

cannot assign to testMap["key"].B

So, why does assigning to the subproperty in a map result in an error while assigning to the subproperty in an array work as expected? I want to know both why this doesn't work for maps AND why it does work for arrays. I would also love some speculation on why they designed the language with this difference between the two data structures.

like image 752
GreenMachine Avatar asked Aug 06 '13 14:08

GreenMachine


People also ask

How do you define an array of structs in Go?

In the Go language, you can set a struct of an array. To do so see the below code example. Where type company struct has a slice of type employee struct. Here, you can see the two different structs, and the employee struct is used as an array in the company struct.

What is difference between array and slice in Golang?

Slices in Go and Golang The basic difference between a slice and an array is that a slice is a reference to a contiguous segment of an array. Unlike an array, which is a value-type, slice is a reference type. A slice can be a complete array or a part of an array, indicated by the start and end index.

Why use a struct over an array?

struct has other advantages over array which can make it more powerful. For example, its ability to encapsulate multiple data types. If you are passing this information between many functions, a structure is likely more practical (because there is no need to pass the size).


1 Answers

I answered at some length on the mailing list, but the short explanation is that this doesn't work because map entries are not addressable. What that means is that you can't take the address of an entry in a map. And that is because adding a new value to a map may cause map entries to shift around, so that the addresses change. Because you can't take the address of an entry in a map, all map operations use whole values: copy a whole value out of a map, add a whole to a map. Assigning to one field of a struct in a map would require a read-modify-write operation, that maps do not support (they could, but they don't, and there is a cost to supporting them).

Elements in arrays and slices are addressable because they do not move around after they have been created.

like image 77
iant Avatar answered Oct 06 '22 03:10

iant