Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can one not assign to arrays inside maps in Go?

Here's a short example to demonstrate:

package main

import "fmt"

func main() {
    array := [3]int{1, 2, 3}
    array[0]++ // Works
    slice := make([]int, 3)
    for i := range slice {
        slice[i] = i + 1
    }
    arrayMap := make(map[int][3]int)
    sliceMap := make(map[int][]int)
    arrayMap[0] = array
    sliceMap[0] = slice
    //arrayMap[0][0]++ // Does not compile: "cannot assign to arrayMap[0][0]"
    sliceMap[0][0]++
    fmt.Println(arrayMap)
    fmt.Println(sliceMap)
}

Why can I not modify the contents of an array if it's inside a map, even though they are mutable outside the map? And why does this work with slices?

like image 918
EMBLEM Avatar asked Apr 02 '16 03:04

EMBLEM


1 Answers

For maps, its values are not addressable. That is, when you use a value type (arrays are value types in Go), you cannot address the value using ++.

But, if you use a reference type (slices are reference types in Go), you can as you already alluded to in the example.

This holds true regardless of type used in the Map.

One thing we can do instead is to use the ptr address of the type. For example, if you take the address of the array, then it should work:

Playground: http://play.golang.org/p/XeIThVewWD

package main

import "fmt"

func main() {
    array := [3]int{1, 2, 3}
    slice := []int{1, 2, 3}

    arrayMap := make(map[int]*[3]int) // use the pointer to the type
    sliceMap := make(map[int][]int)
    arrayMap[0] = &array // get the pointer to the type
    sliceMap[0] = slice

    arrayMap[0][0]++ // works, because it's a pointer to the array
    sliceMap[0][0]++

    fmt.Println(*arrayMap[0])
    fmt.Println(sliceMap[0])
}

// outputs
[2 2 3]
[2 2 3]

This works and increments the [0] index of array to 2, as expected.

It works because Go graciously dereferences pointers for us to its value when read and updates the value during re-assignment.

like image 98
eduncan911 Avatar answered Sep 18 '22 19:09

eduncan911