I have a data structure like this demo. As you can see, foo
has an embedded pointer to bar
:
type foo struct {
*bar
}
type bar struct {
S []byte
}
And I'm using the reflect
package like this:
func test(x interface{}) {
var v = reflect.ValueOf(x)
if v.Kind() == reflect.Struct {
fmt.Println("was a struct")
// panic: reflect: call of reflect.Value.Elem on struct Value
// v = v.Elem()
// panic: reflect: call of reflect.Value.Field on ptr Value
v = v.FieldByName("S")
}
}
func main() {
var f foo
test(f)
fmt.Println(string(f.S))
}
So v.Kind()
is recognized as a reflect.Struct
, but if I try to treat it like a struct by using .FieldByName("S")
, it panics because it thinks v
is a ptr
.
So then if I try to treat it like a ptr
by calling .Elem()
, it panics because it thinks v
is a struct
.
I've tried reflect.Indirect()
, as well as a few other things, but I can't figure out how to get the field of an embedded pointer.
Is there a way to get the reflect.Value
representation from an embedded pointer to a struct?
Demo: http://play.golang.org/p/n0eea6XW3I
EDIT: Also tried v = v.FieldByName("bar")
, but got:
panic: runtime error: invalid memory address or nil pointer dereference
i was getting this error " panic: reflect: call of reflect.Value.Elem on struct Value" bcz of this line "reflect.ValueOf(parameterName).Elem()"
1.When i am using Elem() in reflex ,it means parameterName inside valueOf() should be a pointer to structure
Now while calling search function my call should be like this! result := Search(&flights, key)
The first thing we need to realize is that the line
var f foo
is equivalent tof := foo{}
. This initializes the internal fieldbar
(of type *bar) to its zero value... nil. The behavior of embedded types and reflect seems to be that it treats the embedded type's fields as fields of the type itself. So when you requestv.FieldByName("S")
it's trying to find that field in f's member, bar, which is nil.You're trying to do this
(*f.bar).S
. (In Go the explicit pointer dereference isn't needed, but it makes my point). Now the question is: if you change is tov.FieldByName("bar")
why does it give an error? Same reason.Look closely at the stack trace, the
FieldByName
line no longer crashes, the line that crashes isfmt.Println(string(f.S))
. Again, semantically you're doing(*f.bar).S
. But the member "bar" is nil, so you are, in fact, doing a nil pointer dereference.You can fix both errors by changing
var f foo
tof := foo{&bar{}}
.