reflect runtime error: call of reflect.flag.mustBeAssignable on zero Value - go

I'm testing this code snippet on go playground, I aim to use reflect to get fields from one object, and then set value to another object
package main
import (
"fmt"
"reflect"
)
type T struct {
A int `json:"aaa" test:"testaaa"`
B string `json:"bbb" test:"testbbb"`
}
type newT struct {
AA int
BB string
}
func main() {
t := T{
A: 123,
B: "hello",
}
tt := reflect.TypeOf(t)
tv := reflect.ValueOf(t)
newT := &newT{}
newTValue := reflect.ValueOf(newT)
for i := 0; i < tt.NumField(); i++ {
field := tt.Field(i)
newTTag := field.Tag.Get("newT")
tValue := tv.Field(i)
newTValue.Elem().FieldByName(newTTag).Set(tValue)
}
fmt.Println(newT)
}
And it gives a very strange error:
panic: reflect: call of reflect.flag.mustBeAssignable on zero Value
goroutine 1 [running]:
reflect.flag.mustBeAssignableSlow(0x0, 0x0)
/usr/local/go/src/reflect/value.go:240 +0xe0
reflect.flag.mustBeAssignable(...)
/usr/local/go/src/reflect/value.go:234
reflect.Value.Set(0x0, 0x0, 0x0, 0x100f80, 0x40a0f0, 0x82)
/usr/local/go/src/reflect/value.go:1531 +0x40
main.main()
/tmp/sandbox166479609/prog.go:32 +0x400
Program exited: status 2.
How to fix it?

It is as error call of reflect.flag.mustBeAssignable on zero Value says , newTValue.Elem().FieldByName(newTTag).CanSet() returns false in your your code and according to documentation
Set assigns x to the value v. It panics if CanSet returns false. As in Go, x's value must be assignable to v's type.
This is corrected code that takes fields from one Object and assigns value to another one.
package main
import (
"fmt"
"reflect"
)
type T struct {
A int `json:"aaa" test:"AA"`
B string `json:"bbb" test:"BB"`
}
type newT struct {
AA int
BB string
Testaaa string
}
func main() {
t := T{
A: 123,
B: "hello",
}
tt := reflect.TypeOf(t)
tv := reflect.ValueOf(t)
newT := &newT{}
newTValue := reflect.ValueOf(newT)
for i := 0; i < tt.NumField(); i++ {
field := tt.Field(i)
newTTag := field.Tag.Get("test")
tValue := tv.Field(i)
newTfield := newTValue.Elem().FieldByName(newTTag)
if newTfield.CanSet() {
newTfield.Set(tValue)
}
}
fmt.Println(newT)
}

First:
for i := 0; i < tt.NumField(); i++ {
field := tt.Field(i)
Each step here iterates through the fields of your instance of type T. So the fields will be A—or rather, the field descriptor whose Name is A and which describes an int with its json and test tags—and then B (with the same picky details if we go any further).
Since both field descriptors have only two Get-able items, you probably meant to use Get("test"), as in Guarav Dhiman's answer.
If you do that, though, the result is "testaaa" when you are on field A and "testbbb" when you are on field B. If we annotate Guarav's code a bit more:
for i := 0; i < tt.NumField(); i++ {
field := tt.Field(i)
newTTag := field.Tag.Get("test")
fmt.Printf("newTTag = %#v\n", newTTag)
tValue := tv.Field(i)
newTfield := newTValue.Elem().FieldByName(newTTag)
fmt.Printf("newTfield = %#v\n", newTfield)
if newTfield.CanSet() {
newTfield.Set(tValue)
}
}
we will see this output:
newTTag = "testaaa"
newTfield = <invalid reflect.Value>
newTTag = "testbbb"
newTfield = <invalid reflect.Value>
What we need is to make the test string in each tag name the field in the newT type:
type T struct {
A int `json:"aaa" test:"AA"`
B string `json:"bbb" test:"BB"`
}
(Guarav actually already did this but did not mention it.) Now the program produces what (presumably) you intended:
&{123 hello}
The complete program, with commented-out tracing, is here.

Related

How to dynamically create a struct with one less property?

Is there a way to copy a generic struct (i.e. a struct whose property names are unknown) and skip a single, known property?
Here is what I know:
The parameter to my function--I will call the parameter myData-- is of type interface{}.
myData is a struct.
myData has a known property path.
myData has anywhere from 0 to 6 or so other properties, none of which are known a priori.
Once I remove that path property, then the “leftover” is one of say 30 possible struct types.
So I want to strip path out of myData (or more accurately make a copy that omits path) so that various bits of generated code that try to coerce the struct to one of its possible types will be able to succeed.
I have found examples of copying a struct by reflection, but they typically create an empty struct of the same underlying type, then fill it in. So is it even possible to delete a property as I have outlined...?
You can use reflect.StructOf to dynamically create structs from a list of fields.
package main
import (
"fmt"
"reflect"
)
type A struct {
Foo string
Bar int
Baz bool // to be skipped
}
type B struct {
Foo string
Bar int
}
func main() {
av := reflect.ValueOf(A{"hello", 123, true})
fields := make([]reflect.StructField, 0)
values := make([]reflect.Value, 0)
for i := 0; i < av.NumField(); i++ {
f := av.Type().Field(i)
if f.Name != "Baz" {
fields = append(fields, f)
values = append(values, av.Field(i))
}
}
typ := reflect.StructOf(fields)
val := reflect.New(typ).Elem()
for i := 0; i < len(fields); i++ {
val.Field(i).Set(values[i])
}
btyp := reflect.TypeOf(B{})
bval := val.Convert(btyp)
b, ok := bval.Interface().(B)
fmt.Println(b, ok)
}

How do I use reflection to get slice data?

package main
import (
"fmt"
"reflect"
)
//AuthRequest struct
type AuthRequest struct {
Id int64
}
func main() {
//AuthRequest auth1
auth1 := AuthRequest{
Id : 1111,
}
//Authrequest auth2
auth2 := AuthRequest{
Id : 2222,
}
//create slice
var sliceModel = make([]AuthRequest, 0)
//put element to slice
sliceModel = append(sliceModel, auth1)
sliceModel = append(sliceModel, auth2)
//Pointer to an array
model := &sliceModel
//How do I get the struct Id field here?
v := reflect.ValueOf(model).Elem()
for j := 0; j < v.NumField(); j++ {
f := v.Field(j)
n := v.Type().Field(j).Name
t := f.Type().Name()
fmt.Printf("Name: %s Kind: %s Type: %s\n", n, f.Kind(), t)
}
}
When I execute the above code, I get the following error.
panic: reflect: call of reflect.Value.NumField on slice Value [recovered]
How do I use reflection to traverse slice to get the value of Id field in the struct AuthRequest?
From the docs:
NumField returns the number of fields in the struct v. It panics if v's Kind is not Struct.
Since your input is a slice, not a struct, NumField is supposed to panic.
You probably need the Slice method.

How to access unexported struct fields

Is there a way to use reflect to access unexported fields in Go 1.8?
This no longer seems to work: https://stackoverflow.com/a/17982725/555493
Note that reflect.DeepEqual works just fine (that is, it can access unexported fields) but I can't make heads or tails of that function. Here's a go playarea that shows it in action: https://play.golang.org/p/vyEvay6eVG. The src code is below
import (
"fmt"
"reflect"
)
type Foo struct {
private string
}
func main() {
x := Foo{"hello"}
y := Foo{"goodbye"}
z := Foo{"hello"}
fmt.Println(reflect.DeepEqual(x,y)) //false
fmt.Println(reflect.DeepEqual(x,z)) //true
}
If the struct is addressable, you can use unsafe.Pointer to access the field (read or write) it, like this:
rs := reflect.ValueOf(&MyStruct).Elem()
rf := rs.Field(n)
// rf can't be read or set.
rf = reflect.NewAt(rf.Type(), unsafe.Pointer(rf.UnsafeAddr())).Elem()
// Now rf can be read and set.
See full example on the playground.
This use of unsafe.Pointer is valid according to the documentation and running go vet returns no errors.
If the struct is not addressable this trick won't work, but you can create an addressable copy like this:
rs = reflect.ValueOf(MyStruct)
rs2 := reflect.New(rs.Type()).Elem()
rs2.Set(rs)
rf = rs2.Field(0)
rf = reflect.NewAt(rf.Type(), unsafe.Pointer(rf.UnsafeAddr())).Elem()
// Now rf can be read. Setting will succeed but only affects the temporary copy.
See full example on the playground.
Based on cpcallen's work:
import (
"reflect"
"unsafe"
)
func GetUnexportedField(field reflect.Value) interface{} {
return reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem().Interface()
}
func SetUnexportedField(field reflect.Value, value interface{}) {
reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).
Elem().
Set(reflect.ValueOf(value))
}
reflect.NewAt might be confusing to read at first. It returns a reflect.Value representing a pointer to a value of the specified field.Type(), using unsafe.Pointer(field.UnsafeAddr()) as that pointer. In this context reflect.NewAt is different than reflect.New, which would return a pointer to a freshly initialized value.
Example:
type Foo struct {
unexportedField string
}
GetUnexportedField(reflect.ValueOf(&Foo{}).Elem().FieldByName("unexportedField"))
https://play.golang.org/p/IgjlQPYdKFR
reflect.DeepEqual() can do it because it has access to unexported features of the reflect package, in this case namely for the valueInterface() function, which takes a safe argument, which denies access to unexported field values via the Value.Interface() method if safe=true. reflect.DeepEqual() will (might) call that passing safe=false.
You can still do it, but you cannot use Value.Interface() for unexported fields. Instead you have to use type-specific methods, such as Value.String() for string, Value.Float() for floats, Value.Int() for ints etc. These will return you a copy of the value (which is enough to inspect it), but will not allow you to modify the field's value (which might be "partly" possible if Value.Interface() would work and the field type would be a pointer type).
If a field happens to be an interface type, you may use Value.Elem() to get to the value contained / wrapped by the interface value.
To demonstrate:
type Foo struct {
s string
i int
j interface{}
}
func main() {
x := Foo{"hello", 2, 3.0}
v := reflect.ValueOf(x)
s := v.FieldByName("s")
fmt.Printf("%T %v\n", s.String(), s.String())
i := v.FieldByName("i")
fmt.Printf("%T %v\n", i.Int(), i.Int())
j := v.FieldByName("j").Elem()
fmt.Printf("%T %v\n", j.Float(), j.Float())
}
Output (try it on the Go Playground):
string hello
int64 2
float64 3
package main
import (
"fmt"
"reflect"
"strings"
"unsafe"
)
type Person1 struct {
W3ID string
Name string
}
type Address1 struct {
city string
country string
}
type User1 struct {
name string
age int
address Address1
manager Person1
developer Person1
tech Person1
}
func showDetails(load, email interface{}) {
if reflect.ValueOf(load).Kind() == reflect.Struct {
typ := reflect.TypeOf(load)
value := reflect.ValueOf(load)
//#1 For struct, not addressable create a copy With Element.
value2 := reflect.New(value.Type()).Elem()
//#2 Value2 is addressable and can be set
value2.Set(value)
for i := 0; i < typ.NumField(); i++ {
if value.Field(i).Kind() == reflect.Struct {
rf := value2.Field(i)
/* #nosec G103 */
rf = reflect.NewAt(rf.Type(), unsafe.Pointer(rf.UnsafeAddr())).Elem()
irf := rf.Interface()
typrf := reflect.TypeOf(irf)
nameP := typrf.String()
if strings.Contains(nameP, "Person") {
//fmt.Println(nameP, "FOUND !!!!!!! ")
for j := 0; j < typrf.NumField(); j++ {
re := rf.Field(j)
nameW := typrf.Field(j).Name
if strings.Contains(nameW, "W3ID") {
valueW := re.Interface()
fetchEmail := valueW.(string)
if fetchEmail == email {
fmt.Println(fetchEmail, " MATCH!!!!")
}
}
}
}
showDetails(irf, email)
} else {
// fmt.Printf("%d.Type:%T || Value:%#v\n",
// (i + 1), value.Field(i), value.Field(i))
}
}
}
}
func main() {
iD := "tsumi#in.org.com"
load := User1{
name: "John Doe",
age: 34,
address: Address1{
city: "New York",
country: "USA",
},
manager: Person1{
W3ID: "jBult#in.org.com",
Name: "Bualt",
},
developer: Person1{
W3ID: "tsumi#in.org.com",
Name: "Sumi",
},
tech: Person1{
W3ID: "lPaul#in.org.com",
Name: "Paul",
},
}
showDetails(load, iD)
}

Appending to go lang slice using reflection

For some reason, it appears that adding new element to slice using reflection doesn't update slice itself. This is the code to demonstrate:
package main
import (
"fmt"
"reflect"
)
func appendToSlice(arrPtr interface{}) {
valuePtr := reflect.ValueOf(arrPtr)
value := valuePtr.Elem()
value = reflect.Append(value, reflect.ValueOf(55))
fmt.Println(value.Len()) // prints 1
}
func main() {
arr := []int{}
appendToSlice(&arr)
fmt.Println(len(arr)) // prints 0
}
Playground link : https://play.golang.org/p/j3532H_mUL
Is there something I'm missing here?
reflect.Append works like append in that it returns a new slice value.
You are assigning this value to the value variable in the appendToSlice function, which replaces the previous reflect.Value, but does not update the original argument.
To make it more clear what's happening, take the equivalent function to your example without reflection:
func appendToSlice(arrPtr *[]int) {
value := *arrPtr
value = append(value, 55)
fmt.Println(len(value))
}
What you need to use is the Value.Set method to update the original value:
func appendToSlice(arrPtr interface{}) {
valuePtr := reflect.ValueOf(arrPtr)
value := valuePtr.Elem()
value.Set(reflect.Append(value, reflect.ValueOf(55)))
fmt.Println(value.Len())
}
https://play.golang.org/p/Nhabg31Sju
package main
import "fmt"
import "reflect"
type Foo struct {
Name string
}
func main() {
_type := []Foo{}
fmt.Printf("_type: v(%v) T(%T)\n", _type, _type)
reflection := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(_type).Elem()), 0, 0)
reflectionValue := reflect.New(reflection.Type())
reflectionValue.Elem().Set(reflection)
slicePtr := reflect.ValueOf(reflectionValue.Interface())
sliceValuePtr := slicePtr.Elem()
sliceValuePtr.Set(reflect.Append(sliceValuePtr, reflect.ValueOf(Foo{"a"})))
sliceValuePtr.Set(reflect.Append(sliceValuePtr, reflect.ValueOf(Foo{"b"})))
sliceValuePtr.Set(reflect.Append(sliceValuePtr, reflect.ValueOf(Foo{"c"})))
values := []Foo{Foo{"d"}, Foo{"e"}}
for _, val := range values {
sliceValuePtr.Set(reflect.Append(sliceValuePtr, reflect.ValueOf(val)))
}
result := sliceValuePtr.Interface()
fmt.Printf("result: %T = (%v)\n", result, result)
}
take a look at: https://play.golang.org/p/vXOqTVSEleO

Modify array of interface{} golang

This type assertion, def-referencing has been driving me crazy. So I have a nested structure of Key string / Value interface{} pairs. Stored in the Value is an []interface which I want to modify each of the values. Below is an example of creating an array of Bar and passing it into the ModifyAndPrint function which should modify the top level structure. The problem that I come accross is as written it doesn't actually modify the contents of z, and I can't do a q := z.([]interface{})[i].(Bar) or & thereof.
Is there a way to do this? If so, what combination did I miss?
package main
import "fmt"
type Bar struct {
Name string
Value int
}
func ModifyAndPrint(z interface{}){
fmt.Printf("z before: %v\n", z)
for i, _ := range(z.([]interface{})) {
q := z.([]interface{})[i]
b := (q).(Bar)
b.Value = 42
fmt.Printf("Changed to: %v\n", b)
}
fmt.Printf("z after: %v\n", z)
}
func main() {
bars := make([]interface{}, 2)
bars[0] = Bar{"a",1}
bars[1] = Bar{"b",2}
ModifyAndPrint(bars)
}
https://play.golang.org/p/vh4QXS51tq
The program is modifying a copy of the value in the interface{}. One way to achieve your goal is to assign the modified value back to the slice:
for i, _ := range(z.([]interface{})) {
q := z.([]interface{})[i]
b := (q).(Bar)
b.Value = 42
z.([]interface{})[i] = b
fmt.Printf("Changed to: %v\n", b)
}
playground example

Resources