Reputation: 151
I am having a hard time understanding the below code, I have it working but still don't understand it. It would really helpful if someone can demystify it
In below code Flags name is not updated to "Changed"
package main
import "fmt"
type Command struct {
Name string
Flags []Flag
}
type Flag struct {
Name string
Shorthand string
}
func getCommand() *Command {
return &Command{Name: "Hello", Flags: []Flag{{"version", "v"}}}
}
func change(cmd *Command) {
for _, flg := range cmd.Flags {
flg.Name = "Changed"
}
}
func main() {
cmd := getCommand()
change(cmd)
fmt.Println(cmd.Flags[0])
}
Correct code. Flags Name is changed to "Changed"
package main
import "fmt"
type Command struct {
Name string
Flags []*Flag
}
type Flag struct {
Name string
Shorthand string
}
func getCommand() *Command {
return &Command{Name: "Hello", Flags: []*Flag{{"version", "v"}}}
}
func change(cmd *Command) {
for _, flg := range cmd.Flags {
flg.Name = "Changed"
}
}
func main() {
cmd := getCommand()
change(cmd)
fmt.Println(cmd.Flags[0])
}
I am sure, my confusion might be trivial, but it has wasted my couple of hours
Upvotes: 0
Views: 90
Reputation: 13
for _, flg := range cmd.Flags {
flg.Name = "Changed"
}
This part is the exact culprit. The first value returned by range is the index(which is ignored here), the second value is a copy of the actual data. When you are using it inside the loop(flg.Name=...), You are assigning the value to Name filed of the copy. You may do this:
for index, _ := range cmd.Flags {
cmd.Flags[index].Name = "Changed"
}
In the second case, you are assigning to Name field of a copy of reference(or memory address) to the Flag, so the value at that memory address get changed.
Upvotes: 1
Reputation: 34031
In your first version, when you do this:
for _, flg := range cmd.Flags {
flg.Name = "Changed"
}
flg
is a local variable of type Flag
. On each iteration of the for
loop, range
sets flg
to a copy of the next item in cmd.Flags
. So when you change that, nothing changes outside that loop.
In your second version, when you do that loop, flg
is a local variable of type *Flag
, so when range sets it to a copy of the next item in cmd.Flags
, flg
is pointing to the data you are trying to mutate, and mutating it actually changes that data.
Upvotes: 1