Using a setter function for a struct, but not working as anticipated:
package main
import "fmt"
type T struct { Val string }
// this setter seems not to work
func (t T) SetVal( s string ) {
t.Val = s
}
// this setter, using ptr to T, seems to work ok
func (t *T) SetVal2( s string ) {
(*t).Val = s
}
func main() {
v := T{"abc"}
fmt.Println( v ) // prints {abc}
v.SetVal("pdq")
fmt.Println( v ) // prints {abc}, was expecting {pdq}!
v.SetVal2("xyz")
fmt.Println( v ) // prints {xyz}!
}
I am missing some fundamental understanding - why doesn't SetVal
work?
the behavior is similar to setting values in reflect
which only works if provided a pointer to the object as versus the object itself
Here is the fundamental understanding you are missing: when a struct is passed in to a function as a pointer, the function can modify the original struct because it has a pointer to it. However, when a struct is passed in to a function via its value, then a NEW copy of the struct is actually created just for that function call, and any modifications to this new copy of the struct will not affect the original struct.
You can prove that this is the way it works by printing out the actual addresses of the structs in question:
package main
import "fmt"
type T struct { Val string }
func (t T) SetVal( s string ) {
fmt.Printf("Address of copy is %p\n", &t);
}
func (t *T) SetVal2( s string ) {
fmt.Printf("Pointer argument is %p\n", t);
}
func main() {
v := T{"abc"}
fmt.Printf("Address of v is %p\n", &v);
v.SetVal("pdq")
v.SetVal2("xyz")
}
The code above results in this output when I run it in the Go playground:
Address of v is 0xf840001290
Address of copy is 0xf8400013e0
Pointer argument is 0xf840001290
Notice how the first and third pointer printed out are equal, which means they are the same struct. But the second pointer is different because it is a copy.
This seems to be exactly the same way that C structs / function parameters work, by the way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With