Strange behavior for a pointer of an interface - go

I wrote 3 similar functions to figure out a strange behavior of Go's pointer reflection.
package main
import (
"reflect"
"fmt"
)
var i interface{} = struct {}{} // i is an interface which points to a struct
var ptr *interface{} = &i // ptr is i's pointer
func f(x interface{}) { // print x's underlying value
fmt.Println(reflect.ValueOf(x).Elem())
}
func main1() { // f is asking for interface? OK, I'll use the struct's interface
structValue := reflect.ValueOf(ptr).Elem().Elem().Interface()
f(structValue)
}
func main2() { // Error? Let me try the struct's pointer
structPtr := reflect.ValueOf(ptr).Elem().Interface()
f(structPtr)
}
func main3() { // Why this one could succeed after New() ?
typ := reflect.ValueOf(ptr).Elem().Elem().Type()
newPtr := reflect.New(typ).Elem().Addr().Interface()
f(newPtr)
}
func main() {
//main1() // panic: reflect: call of reflect.Value.Elem on struct Value
//main2() // panic: reflect: call of reflect.Value.Elem on struct Value
main3() // OK. WHY???
}
Only main3 is working, the other 2 would panic. Why?
The key difference of 3 is that it creates a New Value.
As to main2, I think ValueOf().Elem().Interface() has already reconstructed a interface which points at the struct{}{}, just don't understand why it would fail.

The value returned from reflect.ValueOf holds the concrete value stored in the argument. If the argument is nil, the zero reflect.Value is returned.
To put this another way, the reflect.Value and the interface passed to reflect.Value have the same underlying value.
The functions main1 and main2 will work as I think you expect if you f change to:
func f(x interface{}) { // print x's underlying value
fmt.Println(reflect.ValueOf(x))
}
The argument to f in main3 is a *struct{}. The function f dereferences the pointer (with the call to Elem()) and prints the reflect value for the struct{}.
One point that might be confusing is that reflect.ValueOf(ptr).Elem().Elem().Interface() and reflect.ValueOf(ptr).Elem().Interface() return an interface with the same concrete value.
The expression reflect.ValueOf(ptr).Elem() is the reflect value corresponding to i. The call to Interface() on this value returns an interface with the concrete value in i.
The expression reflect.ValueOf(ptr).Elem().Elem() is the reflect value corresponding to i's concrete value. The call to Interface() on this value returns an interface containing that concrete value.

Related

panic: reflect: call of reflect.Value.FieldByName on interface Value

I have a variable of type interface{} and I want to change the value of a field using reflection. How can I do it? Variable must be of type interface{} due to other requirements. If the variable isn't of type interface{} all works, otherwise code throws
reflect: call of reflect.Value.FieldByName on interface Value
my code
package main
import (
"fmt"
"reflect"
)
func main() {
a := struct {
Name string
}{}
// works
reflect.ValueOf(&a).Elem().FieldByName("Name").SetString("Hello")
fmt.Printf("%#v\n", a)
var b interface{}
b = struct {
Name string
}{}
// panics
reflect.ValueOf(&b).Elem().FieldByName("Name").SetString("Hello")
fmt.Printf("%#v\n", b)
}
The application must call Elem() twice to get the struct value:
reflect.ValueOf(&b).Elem().Elem().FieldByName("Name").SetString("Hello")
The first call Elem() dereferences the pointer to interface{}. The second call to Elem() gets the value contained in the interface.
With this change, the panic is reflect.Value.SetString using unaddressable value.
The application cannot set fields directly on the struct value contained in the interface because values contained in an interface are not addressable.
Copy the struct value to a temporary variable, set the field in the temporary variable and copy the temporary variable back to the interface.
var b interface{}
b = struct {
Name string
}{}
// v is the interface{}
v := reflect.ValueOf(&b).Elem()
// Allocate a temporary variable with type of the struct.
// v.Elem() is the vale contained in the interface.
tmp := reflect.New(v.Elem().Type()).Elem()
// Copy the struct value contained in interface to
// the temporary variable.
tmp.Set(v.Elem())
// Set the field.
tmp.FieldByName("Name").SetString("Hello")
// Set the interface to the modified struct value.
v.Set(tmp)
fmt.Printf("%#v\n", b)
Run it on the Go playground.
The interface b is initialized using the value of the anonymous struct, so b contains a copy of the struct, and the values are not addressable. Initialize b using a pointer:
var b interface{}
b = &struct {
Name string
}{}
reflect.ValueOf(b).Elem().FieldByName("Name").SetString("Hello")

How cast type when the original arg is a pointer

So I have this:
v, ok := muxctx.Get(req, "req-body-map").(map[string]interface{})
the problem is that:
muxctx.Get(req, "req-body-map")
returns a pointer. I tried dereferencing the pointer like so:
(*(muxctx.Get(req, "req-body-map"))
but I get this:
Invalid indirect of '(muxctx.Get(req, "req-body-map"))' (type 'interface{}')
so I suppose since the Get method doesn't return a pointer, then I can't dereference it.
Pretty sure you want something like:
// You really want this to be two variables, lest you go mad.
// OK here is mostly to see whether the value exists or not, which is what
// presumably you're testing for. Get that out of the way before trying to
// get fancy with type coercion.
//
ptr, ok := muxctx.Get(req, "req-body-map")
... // Do other stuff (like your if test maybe)...
// Now coerce and deref. We coerce the type inside parens THEN we try to
// dereference afterwards.
//
v := *(ptr.(*map[string]interface{}))
A brief example of this general technique:
package main
import "fmt"
func main() {
foo := 10
var bar interface{}
bar = &foo
fmt.Println(bar)
foobar := *(bar.(*int))
fmt.Println(foobar)
}
$ ./spike
0xc00009e010
10
Finally, be really sure you have the type you want (using reflection if needbe) or risk the program panic'ing on a bad type coercion.
Get method is func (m *muxctx) Get(string) interface{}, return a value type is interface{}, if value is int(1) type is interface{}, if value is map[string]interface{} type return type also interface{}.
so ptr type is interface{} in ptr, ok := muxctx.Get(req, "req-body-map"), must convert interface{} ptr type a need type,example map[string]interface{}:ptr.(*map[string]interface{}), map ptr? ptr.(map[string]interface{}), map double ptr? ptr.(**map[string]interface{})
(*(muxctx.Get(req, "req-body-map")) convert code is invalid syntax, var i interface{}; *i,i type is interface{}, not use * remove pointer,must convert i to a ptr type, example:n := i.(*int); *n or m := i.(*map[string]interface{}); *m.
golang spce doc:
Type assertions
Type switches。
unsafe
Conversions

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
}

Using reflection to populate a pointer to a struct

I'd like to iterate over the fields in a struct and prompt for string values to string fields, doing this recursively for fields that are pointers to structs.
Currently this is what I've tried, but I get an error when trying to set this value in the pointer's string field.
package main
import (
"fmt"
"reflect"
)
type Table struct {
PK *Field
}
type Field struct {
Name string
}
func main() {
PopulateStruct(&Table{})
}
func PopulateStruct(a interface{}) interface {} {
typeOf := reflect.TypeOf(a)
valueOf := reflect.ValueOf(a)
for i := 0; i < typeOf.Elem().NumField(); i++ {
switch typeOf.Elem().Field(i).Type.Kind() {
case reflect.String:
fmt.Print(typeOf.Elem().Field(i).Name)
var s string
fmt.Scanf("%s", &s)
valueOf.Elem().Field(i).SetString(s)
case reflect.Ptr:
ptr := reflect.New(valueOf.Elem().Field(i).Type())
PopulateStruct(ptr.Elem().Interface())
valueOf.Elem().Field(i).Set(ptr)
}
}
}
Expecting the return value to include an initialised struct with the pointers string field set.
Getting an error when setting the pointer's string field.
panic: reflect: call of reflect.Value.Field on zero Value
I dropped your code as-is into the Go Playground and it doesn't build because PopulateStruct is declared as returning interface{} but does not actually return anything. Removing the declared return type produces the panic you mention.
This is because at entry to the outer PopulateStruct call, you have a valid pointer, pointing to a zero-valued Table. A zero-valued Table has one element: a nil pointer in it of type *Field. Your loop therefore runs once and finds a reflect.Ptr, as you expected. Adding more diagnostic print messages helps see what's happening:
fmt.Printf("PopulateStruct: I have typeOf=%v, valueOf=%v\n", typeOf, valueOf)
for i := 0; i < typeOf.Elem().NumField(); i++ {
switch typeOf.Elem().Field(i).Type.Kind() {
// ... snipped some code ...
case reflect.Ptr:
ptr := reflect.New(valueOf.Elem().Field(i).Type())
fmt.Println("after allocating ptr, we have:", ptr.Type(), ptr,
"but its Elem is:", ptr.Elem().Type(), ptr.Elem())
This prints:
PopulateStruct: I have typeOf=*main.Table, valueOf=&{<nil>}
after allocating ptr, we have: **main.Field 0x40c138 but its Elem is: *main.Field <nil>
Given the way PopulateStruct itself is constructed, we must actually allocate a real Field instance now, before calling PopulateStruct. We can do this with:
p2 := ptr.Elem()
ptr.Elem().Set(reflect.New(p2.Type().Elem()))
(code borrowed from json.Unmarshal). Now we can fill in this Field, which has one field named Name of type String.
The overall strategy here is not that great, in my opinion: filling-in probably should take a generic pointer, not specifically a pointer-to-struct pointer. You can then emulate the indirect function in the json unmarshaller. However, the addition of these two lines—creating the target object and making the allocated pointer point to it—suffices to make your existing code run.
(Alternatively, you could just create and return a whole instance from scratch, in which case all you need is the type—but I'm assuming you have a pattern in which only some fields are nil.)
Here's the complete Go Playground example. I made a few other changes as there's nothing to scan from when using the playground.

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