Something terribly weird was going on with my code. I had a fully working program. I decided to turn something from an array of objects to a map of pointers to the objects and everything went kablooie. I’ll show you the code. You’ll probably get it right away.

My initial code was something like this:

type A struct {
        x, y int 
}

type MapB map[int]A

func main() {
        list_A := []A{{x: 0, y: 0}, {x: 1, y: 1}} 

        map_B := MapB{}
        for i, a := range list_A {
                map_B[i] = a
        }
        ...   
}

I had the objects in a list. I copied those into a map. This worked excellently. I was going to do a bunch of operations on that map, including sorting it, and I decided it would get expensive to keep copying object A about. So I used a map of pointers. That’s when everything went kablooie.

 type A struct {
        x, y int 
}

type MapB map[int]*A

func main() {
        list_A := []A{{x: 0, y: 0}, {x: 1, y: 1}} 

        map_B := MapB{}
        for i, a := range list_A {
                map_B[i] = &a
        }   
}

Every entry of my map now contained just one value of list_A. After much gnashing of teeth and reduction of code to the smallest reproducible unit (this was a working program which had grown somewhat in size) I discovered that 1) All the map entries were taking the value of the last element of the list and 2) The pointers had the same value.

(No I did not have unit tests. Most of my code involves calling out to the internet and I haven’t learned how to mock those calls in golang yet)

After some investigation I realized what was happening, and a careful reading of the documentation confirmed it: range returns a copy of the item [1, 2] and in fact, the gotcha I ran into is explicitly called out, in the documentation as a gotcha. I’m my code a is a variable instantiated for the loop block, and it keeps getting assigned to a copy of a list element. It’s address remains the same and that is what is set for every entry of the map. That address (variable) ends with a copy of the last list element.