Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can not assign to pair in a map

Tags:

dictionary

go

I have the following pair defined in my go program

type pair struct {
  a float64
  b float64
}

Then I create a map:

dictionary map[string]pair

I first add one element:

dictionary["xxoo"] = pair{5.0, 2.0}

Then I am trying to do this:

dictionary["xxoo"].b = 5.0  // try to change from 2.0 to 5.0

The last line doesn't compile and it said "can not assign to it"

I want to know what's the reason for this?

like image 516
WhatABeautifulWorld Avatar asked Jul 06 '16 18:07

WhatABeautifulWorld


3 Answers

In order to assign a value to a struct field, that struct must be "addressable". Addressability is covered in the "Address Operators" section of the language specification.

Map values aren't addressable to leave map implementations the freedom to move values around in memory as needed. Because map values aren't addressable, you you can't use a selector (.) operator on the value to assign to the struct field. If you use a pointer type as the map value, i.e. map[string]*pair, the pointer indirection satisfies the addressability requirement.

dict := make(map[string]*pair)
dict["xxoo"] = &pair{5.0, 2.0}
dict["xxoo"].b = 5.0

If you are working with values, you need to copy the existing value via assignment, or supply an entirely new value:

dict := make(map[string]pair)
dict["xxoo"] = pair{5.0, 2.0}

// copy the value, change one field, then reassign
p := dict["xxoo"]
p.b = 5.0
dict["xxoo"] = p

// or replace the value in full
dict["xxoo"] = pair{5.0, 5.0}
like image 145
JimB Avatar answered Oct 23 '22 04:10

JimB


That's not legal for reasons described here:

Querying a map give a copy of the stored item, so there is no point assigning to it.

The recommended workaround is:

var xxoo = dictionary["xxoo"]
xxoo.b = 5.0
dictionary["xxoo"] = xxoo
like image 40
Thomas Avatar answered Oct 23 '22 03:10

Thomas


It's forbidden as said in Thomas' answer. Use pointers instead.

dict := map[string]*pair{}
dict["xxoo"] = &pair{5.0, 2.0}
fmt.Println(dict["xxoo"].b) // 2
dict["xxoo"].b = 5.0
fmt.Println(dict["xxoo"].b) // 5

https://play.golang.org/p/nEr_WrQOly

like image 2
ferhat Avatar answered Oct 23 '22 03:10

ferhat