Go: Range is by Value
TL;DR: The value for each item in a
range
loop is not by reference. Instead, use the indexindex := range foos.Bars
and index to the item&foos.Bars[index]
.
I learned a practical lesson today about how the range
keyword works in Go. Here's the scenario. I have a struct graph that looks something like this:
type Foo struct {
Bars []Bar
}
type Bar struct {
Name string
}
Then, I'm ranging over them, like this:
for _, bar := range foos.Bars {
setBarName(&bar)
}
for _, bar := range foos.Bars {
log.Println("Bar Name:", bar.Name)
}
The log statement reveals that the Name
field is never set on a bar. As it turns out, when you use range
to enumerate items, it will give you a copy of the item instead of a reference to the item. To achieve the desired behavior, we can use the index to get to the item in the collection.
for index := range foo.Bars {
setBarName(&foo.Bars[index])
}
for index := range foo.Bars {
log.Println("Bar Name:" + foo.Bars[index].Name)
}