I wrote a function to make a type marshalable, so the main idea is to change all types of keys for maps to string. Here's the function:
type A struct {
MA map[int]*B
MB *B
}
type B struct {
IB int
}
func GetMarshableStruct(src interface{}) interface{} {
t := reflect.TypeOf(src)
v := reflect.ValueOf(src)
kind := t.Kind()
fmt.Printf("kind %s\n", kind)
var result reflect.Value
switch kind {
case reflect.Map:
//Find the map layer count
layer := 0
cur := t.Elem()
for reflect.Map == cur.Kind() {
layer++
cur = cur.Elem()
}
result = reflect.MakeMap(reflect.MapOf(reflect.TypeOf("a"), cur))
for layer > 0 {
result = reflect.MakeMap(reflect.MapOf(reflect.TypeOf("a"), result.Type()))
layer--
}
keys := v.MapKeys()
for _, k := range keys {
result.SetMapIndex(reflect.ValueOf(fmt.Sprintf("%v", k)), reflect.ValueOf(GetMarshableStruct(v.MapIndex(k).Interface())))
}
case reflect.Slice, reflect.Array:
result = reflect.MakeSlice(t, v.Len(), v.Cap())
for i := 0; i < v.Len(); i++ {
result.Index(i).Set(reflect.ValueOf(GetMarshableStruct(v.Index(i).Interface())))
}
case reflect.Ptr:
result = reflect.New(v.Elem().Type())
result.Elem().Set(reflect.ValueOf(GetMarshableStruct(reflect.Indirect(v).Interface())))
case reflect.Struct:
structFields := make([]reflect.StructField, 0)
fieldValues := make([]reflect.Value, 0)
for i := 0; i < v.NumField(); i++ {
tmpV := reflect.ValueOf(GetMarshableStruct(v.Field(i).Interface()))
fieldValues = append(fieldValues, tmpV)
sf := reflect.StructField{}
sf = t.Field(i)
sf.Type = tmpV.Type()
structFields = append(structFields, sf)
}
resultT := reflect.StructOf(structFields)
result = reflect.Indirect(reflect.New(resultT))
for i := 0; i < v.NumField(); i++ {
fmt.Printf("%s\n", result.Field(i).Type())
result.Field(i).Set(fieldValues[i])
}
default:
result = v
}
return result.Interface()
}
func main() {
a := new(A)
a.MA = make(map[int]*B)
a.MA[4] = new(B)
a.MA[4].IB = 2
a.MB = new(B)
a.MB.IB = 3
b := GetMarshableStruct(a)
fmt.Printf("%T %v %T %v\n", a, a, b, b)
}
But I got the error:
panic: reflect.Set: value of type struct { MA map[string]*main.B; MB *main.B } is not assignable to type main.A
goroutine 1 [running]:
panic(0x4c67c0, 0xc42000a550)
/usr/local/go/src/runtime/panic.go:500 +0x1a1
reflect.Value.assignTo(0xc4200721e0, 0xc42000a540, 0x99, 0x4eb8eb, 0xb, 0x4d4200, 0x0, 0x1, 0xc4200721e0, 0xc42000a540)
/usr/local/go/src/reflect/value.go:2163 +0x35c
reflect.Value.Set(0x4d4200, 0xc42000a3b0, 0x199, 0xc4200721e0, 0xc42000a540, 0x99)
/usr/local/go/src/reflect/value.go:1333 +0xa4
main.GetMarshableStruct(0x4c0ca0, 0xc42000a370, 0x4, 0xc42008e048)
/home/bzhang/devCodeCore/common/src/go/src/audience/scanner/ref.go:149 +0x12e7
main.main()
/home/bzhang/devCodeCore/common/src/go/src/audience/scanner/ref.go:114 +0x16a
exit status 2
So it seems that when Set() is invoked, the receiver and the parameter must be the same in name? can anyone help with the problem? We can see that the generated struct : struct { MA map[string]*main.B; MB *main.B } is identical to main.A.
Aucun commentaire:
Enregistrer un commentaire