Set value of interface representing nil pointer using reflect in Go - go

My question is similar to How to initialize struct pointer via reflection.
I have an interface that represents a nil pointer. I want to update the value behind the nil pointer.
I took the code from one of the examples in the answers to the question mentioned above, but my situation is slightly different, and the given solution isn't working.
Inside InitNilPointer() the value actually does become &Foo{}. But the result at the call site remains (*Foo)(nil). How can I use reflect to update foo in main() to &Foo{}?
The situation is the following
func main() {
var foo *Foo
InitNilPointer(foo)
// Want: &main.Foo{A:""}
fmt.Printf("Want: %+#v\n", &Foo{})
// Got: (*main.Foo)(nil)
fmt.Printf("Got: %+#v\n", foo)
}
// InitNilPointer initiates the given pointer to a nil value to become a pointer to
// a value. E.g. (*Foo)(nil) becomes &Foo{}.
func InitNilPointer(source interface{}) {
v := reflect.ValueOf(source)
if reflect.Indirect(v).IsValid() {
return
}
rv := reflect.ValueOf(&source).Elem()
t := rv.Elem().Type().Elem()
// This only updates the value locally. The call site still has a nil pointer. SAD.
rv.Set(reflect.New(t))
// source: &main.Foo{A:""}
fmt.Printf("source: %+#v\n", source)
}

Whatever you pass to a function, a copy is made. If you pass foo, no matter what the function does, it can only modify the copy but not the original foo variable.
So you must pass &foo (and modifying the pointed object will modify foo):
func main() {
var foo *Foo
InitNilPointer(&foo)
fmt.Printf("Want: %+#v\n", &Foo{})
fmt.Printf("Got: %+#v\n", foo)
}
func InitNilPointer(source interface{}) {
rv := reflect.ValueOf(source).Elem()
if reflect.Indirect(rv).IsValid() {
return
}
t := rv.Type().Elem()
rv.Set(reflect.New(t))
// source: &main.Foo{A:""}
fmt.Printf("source: %+#v\n", source)
}
This will output (try it on the Go Playground):
source: (**main.Foo)(0xc00000e028)
Want: &main.Foo{A:""}
Got: &main.Foo{A:""}

Related

why does golang nil pointer dereference happen in submethods

I have this code
package main
import "fmt"
type Foo struct {
Bar string
}
func (f *Foo) level4() {
fmt.Printf("Bar = %s\n", f.Bar)
}
func (f *Foo) level3() {
f.level4() // panics here, 2 levels down
}
func (f *Foo) level2() {
f.level3()
}
func (f *Foo) level1() {
f.level2()
}
type FooWrapper struct {
foo *Foo
}
func main() {
w := FooWrapper{}
w.foo.level1() // expected it to panic here, since foo is nil
}
As expected, running this gives
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x47f454]
However, I expected the nil pointer dereference to happen at w.foo.level1(), since foo is nil. Instead, it calls levels 1, 2 and 3 and panics there. Why is this the case?
playground link
Why is this the case?
Because w.foo.level1() is valid statement and similarly f.level2(), f.level3(), f.level4() are also a valid statement.
try this
func (f *Foo) level1() {
println("Hello Go")
f.level2()
}
it will print Hello Go and call f.level2() and also see last call level 4
func (f *Foo) level4() {
println("Hello Go 4")
fmt.Printf("Bar = %s\n", f.Bar)
}
it will print Hello Go 4 but panic on next line it is showing the trace or you can say origin of error
The default value of any pointer type is nil.
As you are constructing your object using
w := FooWrapper{}
The value of foo will be assigned the default nil.
To resolve the problem you should pass a value for foo.
w := FooWrapper{foo: &Foo{Bar: "bar"}}
What I usually do to prevent this issue is to make some constructor function.
func NewFooWrapper() *FooWrapper {
return &FooWrapper{foo: &Foo{Bar: "bar"}}
}
w := NewFooWrapper()
Or in case the value of foo can't be hardcoded.
func NewFooWrapper(foo *Foo) *FooWrapper {
return &FooWrapper{foo: foo}
}
w := NewFooWrapper(&Foo{Bar: "bar"})
This makes it more explicit from a coding point of view preventing these errors in other places of code.
You did not initialize the FooWrapper in your main function correctly. Your foo field with type *Foo is nil inside w variable type of FooWrapper because you have not assigned a value for that and the default value for a pointer type variable is nil in Go
Simple correct initialization as follows
w := FooWrapper{
foo: &Foo{
Bar: "bar",
},
}
run in playground
output :
Bar = bar
The reason that panic doesn't come in level1(), level2(), level3() is because they are not using any Foo's fields inside those functions. And also in level4() panic occurs not because of the function call, but because it's using f.Bar in print.
In Go,
If the concrete value inside the interface itself is nil, the method will be called with a nil receiver.
You can find a simple example for this in https://go.dev/tour/methods/12
And also you can find a great explanation for this in Go specs documentation under Calls
A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()

invoke a method from a new instance (reflect.New) with reflection

I want to instantiate an object in Go using reflection and call a method on it. However, I have no idea how to do this. I have tried something, but it does not work.
type foo struct {
name string
}
func (f *foo) Bar() {
f.name = "baz"
fmt.Println("hi " + f.name)
}
func main() {
t := reflect.TypeOf(&foo{})
fooElement := reflect.New(t).Elem()
fooElement.MethodByName("Bar").Call([]reflect.Value{})
}
reflect.New works exactly like the new function, in that it returns an allocated pointer to the given type. This means you want pass the struct, not a pointer to the struct, to reflect.TypeOf.
t := reflect.TypeOf(foo{})
fooV := reflect.New(t)
Since you now have a pointer value of the correct type, you can call the method directly:
fooV.MethodByName("Bar").Call(nil)
https://play.golang.org/p/Aehrls4A8xB

How do I call a method by string variable?

I've seen this asked here before. But I don't understand the answers.
How do I call a method from a string value. So if the
I have many methods that are
func (c *something) whateverName(whatever map[string]interface{}) {
}
Same argument type in each one. no returns etc... Literally the only difference in the method name.
I'm looking to do something like this, and I just can't get it to work. I just want to call the correct method from the value of "var myMethod string":
func (c something) foo(m map[string]interface{}) {
fmt.Println("foo..")
//do something with m
}
func main() {
myMethod := "foo"
message := make(map[string]interface{})
//fill message with stuff...
c := something{} //this is just a hypothetical example...
vt := reflect.ValueOf(c)
vm := vt.MethodByName(myMethod)
vm.Call([]reflect.Value{reflect.ValueOf(message)})
}
I'm obviously not understanding how reflection works.
Your example works if you export the method. Change foo to Foo:
type something struct{}
func (c something) Foo(m map[string]interface{}) {
fmt.Println("Foo..")
//do something with m
}
func main() {
myMethod := "Foo"
message := make(map[string]interface{})
//fill message with stuff...
c := something{} //this is just a hypothetical example...
vt := reflect.ValueOf(c)
vm := vt.MethodByName(myMethod)
vm.Call([]reflect.Value{reflect.ValueOf(message)})
}
This will output (try it on the Go Playground):
Foo..
Also note that in this example Foo() has value receiver: c something. If the method has a pointer receiver such as c *something, you need to have a pointer value to start with, because a method with a pointer receiver is not in the method set of the non-pointer type.
See related: Call functions with special prefix/suffix

Is empty interface in golang as function argument is Pass by Value or pointer

If I have function like this
func TestMethod ( d interface{} ) {
}
If I am calling this as
TestMethod("syz")
Is this pass by value or pass by pointer ?
To summarise some of the discussion in the comments and answer the question:
In go everything in Go is passed by value. In this case the value is an interface type, which is represented as a pointer to the data and a pointer to the type of the interface.
This can be verified by running the following snippet (https://play.golang.org/p/9xTsetTDfZq):
func main() {
var s string = "syz"
read(s)
}
//go:noinline
func read(i interface{}) {
println(i)
}
which will return (0x999c0,0x41a788), one pointer to the data and one pointer to the type of interface.
Updated: Answer and comments above are correct. Just a lite bit of extra information.
Some theory
Passing by reference enables function members, methods, properties,
indexers, operators, and constructors to change the value of the
parameters and have that change persist in the calling environment.
Little code sniped to check how function calls work in GO for pointers
package main_test
import (
"testing"
)
func MyMethod(d interface{}) {
// assume that we received a pointer to string
// here we reassign pointer
newStr := "bar"
d = &newStr
}
func TestValueVsReference(t *testing.T) {
data := "foo"
dataRef := &data
// sending poiner to sting into function that reassigns that pointer in its body
MyMethod(dataRef)
// check is pointer we sent changed
if *dataRef != "foo" {
t.Errorf("want %q, got %q", "bar", *dataRef)
}
// no error, our outer pointer was not changed inside function
// confirms that pointer was sent as value
}

golang - Pointer idiosyncrasies

Need help understanding why this breaks. PrintFoo can be called using either pointer or value. Why not NumField?
http://play.golang.org/p/Kw16ReujRx
type A struct {
foo string
}
func (a *A) PrintFoo(){
fmt.Println("Foo value is " + a.foo)
}
func main() {
a := &A{foo: "afoo"}
(*a).PrintFoo() //Works - no problem
a.PrintFoo() //Works - no problem
reflect.TypeOf(*a).NumField() //Works - no problem - Type = main.A
reflect.TypeOf(a).NumField() //BREAKS! - Type = *main.A
}
From the documentation :
// NumField returns the number of fields in the struct v.
// It panics if v's Kind is not Struct.
func (v Value) NumField() int
You are calling it on a pointer, you have to call it on a struct instead, for example :
fmt.Println(reflect.Indirect(reflect.ValueOf(a)).NumField())
fmt.Println(reflect.Indirect(reflect.ValueOf(*a)).NumField())
When you're not sure if your value is a pointer or not, use reflect.Indirect:
Indirect returns the value that v points to. If v is a nil pointer,
Indirect returns a zero Value. If v is not a pointer, Indirect returns
v.
//edit:
NumField gets called on Value, not your actual object, for example of you do:
func main() {
a := &A{foo: "afoo"}
fmt.Printf("%#v\n", reflect.TypeOf(*a))
fmt.Printf("%#v\n", reflect.TypeOf(a))
}
You will get :
//*a
&reflect.rtype{size:0x8, ...... ptrToThis:(*reflect.rtype)(0xec320)}
//a
&reflect.rtype{size:0x4, ...... ptrToThis:(*reflect.rtype)(nil)}
As you can tell, it's a completely different beast.
The first one holds information about the pointer, hence ptrToThis points to the actual struct.
The second holds info about the struct itself.

Resources