Golang: accessing map object outside the function it was declared in

I would like to loop through a slice of structs, and populate a struct field (which is a map) by passing in each struct to a function.

I have the below struct

type thing struct {
    topicThing map[string]int
}

and I have the below functions

func main() {
    ths := make([]thing, 0)
    for i := 0; i < 10; i++ {
        var th thing
        ths = append(ths, th)
    }

    for _, th := range ths {
        dothing(&th)
    }

    for _, th := range ths {
        fmt.Println(th.topicThing)
    }
}

func dothing(th *thing) {
    tc := make(map[string]int)
    tc["Hello"] = 1
    tc["Bye"] = 2
    th.topicThing = tc
}

The main function creates a slice of things (refered as ths), and passes each thing to the dothing() function by iterating over them. Within dothing(), I create a new map, populate it with data, and assigns it to the passed in thing's attribute. However, by the time we iterate over ths in the main function to print topicThing of each thing, the map is empty.

Since make() creates objects within the heap, I was hoping it would be accessible even outside of the function scope. Can anyone tell me why this is happening?

P.S. if I change the dothing() function like below:

func dothing(th *thing) {
    th.topicThing["Hello"] = 1
    th.topicThing["Bye"] = 2
}

The code works as expected, meaning the map is populated with data when accessed in the main function.


Solution 1:

The range copies your object. So when you do this,

    for _, th := range ths {
        dothing(&th)
    }

you are actually dothing on a copy.

For example, with this main:

func main() {
    ths := make([]thing, 0)
    for i := 0; i < 10; i++ {
        var th thing
        ths = append(ths, th)
    }

    for _, th := range ths {
        dothing(&th)
        fmt.Println(th.topicThing)
    }

it will print the right thing, since we are still working on the copy.

In order to not copy, use the array index:

    for idx, _ := range ths {
        dothing(&ths[idx])
    }