Reflection type and value in Go - reflection

I'm not very clear about what this code snippet behaves.
func show(i interface{}) {
switch t := i.(type) {
case *Person:
t := reflect.TypeOf(i) //what t contains?
v := reflect.ValueOf(i) //what v contains?
tag := t.Elem().Field(0).Tag
name := v.Elem().Field(0).String()
}
}
What is the difference between the type and value in reflection?

reflect.TypeOf() returns a reflect.Type and reflect.ValueOf() returns a reflect.Value. A reflect.Type allows you to query information that is tied to all variables with the same type while reflect.Value allows you to query information and preform operations on data of an arbitrary type.
Also reflect.ValueOf(i).Type() is equivalent to reflect.TypeOf(i).
In the example above, you are using the reflect.Type to get the "tag" of the first field in the Person struct. You start out with the Type for *Person. To get the type information of Person, you used t.Elem(). Then you pulled the tag information about the first field using .Field(0).Tag. The actual value you passed, i, does not matter because the Tag of the first field is part of the type.
You used reflect.Value to get a string representation of the first field of the value i. First you used v.Elem() to get a Value for the struct pointed to by i, then accessed the first Field's data (.Field(0)), and finally turned that data into a string (.String()).

Related

reflect.Pointer() returned value is not the value address

type BookInfo struct {
Meta *TableMeta
...
}
func (si *schemaInfo) getTabInfo(obj interface{}) (*tabInfo, error) {
typ := reflect.TypeOf(obj)
val := reflect.ValueOf(obj)
if typ.Kind() != reflect.Ptr {
return nil, errors.New("nborm.schemaInfo.getDBInfo() error: required a pointer")
}
meta := *(**TableMeta)(unsafe.Pointer(val.Pointer()))
...
}
getTabInfo() works well, but I want to know why val.Pointer() return a value of **TableMeta? Why not a *TableMeta?The document of reflect says,
Pointer returns v's value as a uintptr. It returns uintptr instead of
unsafe.Pointer so that code using reflect cannot obtain
unsafe.Pointers without importing the unsafe package explicitly. It
panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or
UnsafePointer.
In my mind:
info := &BookInfo{}
val := reflect.ValueOf(info)
ptr := val.Pointer()
meta := (*TableMeta)(unsafe.Pointer(val.Pointer()))
should work, but infact when I called val.Pointer(), the returned value is the pointer of *TableMeta(**TableMeta).
The value you have is a pointer to a BookInfo struct, it is of type *BookInfo. And the type of BookInfo.Meta field is also a pointer, it is of type *TableMeta, thus a *BookInfo can then be looked at as **TableMeta, hence the "double" pointer.
It's true that the struct pointer points to its first field, but don't build on it. It's fragile. If you add a field before it, it'll break badly (which will only happen at runtime, no compile time messages due to package unsafe).
So if the value is of type *BookInfo, simply obtain that out of the reflect.Value wrapper, then you can refer to its field like value.Meta, which will be of type *TableMeta. Avoid using package unsafe, especially if it's not needed.

If the type of a parameter is interface{} how do you know whether you pass by pointer or by value?

Given any function that takes a parameter of type interface{} how would I know whether or not to pass that parameter with or without & without navigating the source code of the function.
For example if I had a function with this type signature given to me:
func foo(x interface{}, y int) int
Would there be any way to figure out if x was supposed to be passed by value or by pointer?
Here is the snippet from the source:
// DecodeElement works like Unmarshal except that it takes
// a pointer to the start XML element to decode into v.
// It is useful when a client reads some raw XML tokens itself
// but also wants to defer to Unmarshal for some elements.
func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
val := reflect.ValueOf(v)
if val.Kind() != reflect.Ptr {
return errors.New("non-pointer passed to Unmarshal")
}
return d.unmarshal(val.Elem(), start)
}
It is checking val.Kind() != reflect.Ptr Which means you have to pass the pointer i.e &v.
Its entirely depend on the person who wrote the method or function, so interface{} could be either *ptr or anything but u ve to check that inside your function using reflect.ValueOf(v).Kind() whether the value is a pointer or not and proceeds accordingly.
And little bit about empty interface:
The interface type that specifies zero methods is known as the empty interface:
interface{}
An empty interface may hold values of any type. (Every type implements at least zero methods.)
Empty interfaces are used by code that handles values of unknown type. For example, fmt.Print takes any number of arguments of type interface{}.
Another useful discussion: docs
DecodeElement() and friends have a formal v interface{} whose type is documented in the Unmarshal() function documentation:
Unmarshal parses the XML-encoded data and stores the result in the
value pointed to by v, which must be an arbitrary struct, slice, or
string.
So to literally answer your question, no, you cannot know without reading the source - if the value you want to pass is a struct proper, you need to indirect. If it is already a pointer to that struct, you do not.
For example:
type Result struct {
XMLName xml.Name `xml:"Person"`
Name string `xml:"FullName"`
Phone string
Email []Email
Groups []string `xml:"Group>Value"`
Address
}
var (
a Result
b *Result
c string
)
xmlDecoder.DecodeElement(&a, startElement)
xmlDecoder.DecodeElement(&c, startElement)
but
xmlDecoder.DecodeElement(b, startElement)

How to get the underlying type of the pointer using reflect?

What I want is to get the fields of A through B, like
type A struct {
Field_1 string
}
type B struct {
*A
}
fieldsOfA := someMagicFunc(&B{})
You can get the Value reflect object of some variable with reflect.ValueOf().
If you also want to modify the variable or its fields, you have to pass the address (pointer) of the variable to ValueOf(). In this case the Value will belong to the pointer (not the pointed value), but you can use Value.Elem() to "navigate" to the Value of the pointed object.
*A is embedded in B, so fields of A can be referenced from a value of B. You can simply use Value.FieldByName() to access a field by name in order to get or set its value.
So this does the work, try it on Go Playground:
b := B{A: &A{"initial"}}
fmt.Println("Initial value:", *b.A)
v := reflect.ValueOf(&b).Elem()
fmt.Println("Field_1 through reflection:", v.FieldByName("Field_1").String())
v.FieldByName("Field_1").SetString("works")
fmt.Println("After modified through reflection:", *b.A)
Output:
Initial value: {initial}
Field_1 through reflection: initial
After modified through reflection: {works}
I recommend to read this blog post to learn the basics of the reflection in Go:
The Laws of Reflection

Convert Value type to Map in Golang?

I'm getting this return value from a function call in the "reflect" package:
< map[string]string Value >.
Wondering if I can access the actual map inside the return value and if so, how?
EDIT:
So this is where I'm making the call which returns the Value object.
It returns [< map[string]string Value >] to which I grab the first object in that array. However, I'm not sure how to convert [< map[string]string Value >] into a regular map.
view_args := reflect.ValueOf(&controller_ref).MethodByName(action_name).Call(in)
Most reflect Value objects can be converted back to a interface{} value using the .Interface() method.
After obtaining this value, you can assert it back to the map you want. Example (play):
m := map[string]int{"foo": 1, "bar": 3}
v := reflect.ValueOf(m)
i := v.Interface()
a := i.(map[string]int)
println(a["foo"]) // 1
In the example above, m is your original map and v is the reflected value. The interface value i, acquired by the Interface method is asserted to be of type map[string]int and this value is used as such in the last line.
To turn the value in a reflect.Value into an interface{}, you use iface := v.Interface(). Then, to access that, you use a type assertion or type switch.
If you know you're getting a map[string]string the assertion is simply m := iface.(map[string]string). If there's a handful of possibilities, the type switch to handle them all looks like:
switch item := iface.(type) {
case map[string]string:
fmt.Println("it's a map, and key \"key\" is", item["key"])
case string:
fmt.Println("it's a string:", item)
default:
// optional--code that runs if it's none of the above types
// could use reflect to access the object if that makes sense
// or could do an error return or panic if appropriate
fmt.Println("unknown type")
}
Of course, that only works if you can write out all the concrete types you're interested out in the code. If you don't know the possible types at compile time, you have to use methods like v.MapKeys() and v.MapIndex(key) to work more with the reflect.Value, and, in my experience, that involves a long time looking at the reflect docs and is often verbose and pretty tricky.

Golang reflection.Value behaviour

I'm currently getting desperate over the behaviour of golangs reflect package, which to me doesn't seem consistent at all.
1) As far as I understand it, a reflect.Value seems to carry a pointer to the underlying value.
E.g. if I call
var s string
v1 := reflect.ValueOf(&s).Elem()
v2 := v1
v2.SetString("Hello World!")
fmt.Println(s)
It prints me "Hello World!".
However, this doesn't seem to hold true for a reflect.Value obtained by a call to Field().
val := ... //Assign a reflect.Value to it
nextval := val.Field(0) //Make sure that Field exists and is of type map
nextval = reflect.MakeMap(reflect.MapOf(KEY, ELEM))
nextval.SetMapIndex(Some_value_of_type_KEY, Something_of_type_ELEM)
fmt.Println(nextval.MapKeys()
fmt.Println(val.Field(index).MapKeys())
This prints
[Some_value_of_type_KEY]
[]
which is a major annoyance. Anyone knows why this is the case?
===================================================
2) Consider the function
func Test(v interface{}) {
val := reflect.ValueOf(v)
if val.Kind() != reflect.Struct {
fmt.Println("It is a struct")
}
}
If I call it with any struct as an argument it prints "This is a struct".
However, I won't be able to assign new values to stuff inside v by using val,
due to the value not being addressable. Working around by the following:
func Test(v interface{}) {
val := reflect.ValueOf(&v).Elem()
if val.Kind() != reflect.Struct {
fmt.Println("This never get's printed!")
}
}
According to the doc, I would assume, that by taking the '&' I use a pointer to v and by the call of Elem() I get the element it points to, therefore val.Kind() should still return the same thing. It doesn't. val.Kind() now is a reflect.Interface.
Is there a way of not having to go
valForTestingKind := reflect.ValueOf(v)
valForSettingNewValue := reflect.ValueOf(&v).Elem()
as this somehow feels wrong.
Part 1:
By assigning to nextval, you are breaking its association with the original val. Instead, use the Set() method.
nextval.Set(reflect.MakeMap(reflect.MapOf(KEY, ELEM)))
Set() is the equivalent of assignment in the reflection world. Of course, you must make sure it is assignable using reflect.ValueOf(&v).Elem() as you do in your first code example.
Part 2:
The issue here is that you have another level of indirection. v is of type interface{} and has a concrete value whose type is of Kind struct. Just like with every function that accepts an interface typed parameter, when you call reflect.ValueOf, the parameter is automatically converted to that type. However, converting an interface to another interface results in the concrete value being reboxed in the new interface type. The information of the type before it was reboxed is lost. As an example, a function that accepts an io.Writer would not know that the calling function considered it an io.ReaderWriter.
In this context, it means that reflect.ValueOf cannot tell if you passed an os.File (some struct) or a file boxed in an interface{}. It assumes you passed an os.File and shows you the Kind "struct".
However, when you pass a pointer to an interface{}, you are passing an interface{} variable that can be modified. You are not passing the underlying concrete type and that has important consequences. You can .Set() anything, not just what the original concrete type allows. You also can't edit individual fields as anything in an interface{} is not assignable. If the concrete type is in fact a pointer, you can do a fourth dereference (.Elem()) and modify fields from there.
So, what does this mean in terms of code?
//let v = an interface{} with a concrete type of SomeStruct
val := reflect.ValueOf(&v).Elem()
fmt.Println(val.Elem().Kind()) // struct
val.Elem().Field(0).Set(10) // PANIC! Field isn't assignable.
val.Set("a string which is not a SomeStruct")
fmt.Println(val.Elem().Kind()) // string
I made an example here: http://play.golang.org/p/6MULn3KoNh
I want to talk about your second block of code:
val := ... //Assign a reflect.Value to it
nextval := val.Field(0) //Make sure that Field exists and is of type map
nextval = reflect.MakeMap(reflect.MapOf(KEY, ELEM))
nextval.SetMapIndex(Some_value_of_type_KEY, Something_of_type_ELEM)
fmt.Println(nextval.MapKeys()
fmt.Println(val.Field(index).MapKeys())
On the third line, you are reassigning a new, different object to the variable nextval. Shouldn't you call some kind of setting method on nextval instead of reassigning it? In your first example, you called SetString but in this example you are just reassigning the variable and that might be why the behavior is different. After you reassign the variable, nextval will no longer be connected in any way to val.Field(0). Also, what is index?
If this does not explain your problem, please edit the question to contain a short, self-contained, correct, compilable example ( SSCCE ). I want to be able to post it into the text box on the front page of golang.org in order to see the problem. You should always post an SSCCE when possible.
You have not shown a complete and compilable code. Do you pass a pointer to a struct or do you pass the struct by value? In the later case reflection cannot mutate it.
Values stored in a map are not addressable even when not using reflection.
http://play.golang.org/p/wYLeJ3W4R2
http://play.golang.org/p/ttUGBVh1lc
https://groups.google.com/forum/#!topic/golang-nuts/jzjEXoc9FwU
https://groups.google.com/forum/#!topic/golang-nuts/V_5kwzwKJAY

Resources