github.com/gogf/gf/v2@v2.7.4/util/gconv/gconv_maptomap.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gconv 8 9 import ( 10 "reflect" 11 12 "github.com/gogf/gf/v2/errors/gcode" 13 "github.com/gogf/gf/v2/errors/gerror" 14 ) 15 16 // MapToMap converts any map type variable `params` to another map type variable `pointer` 17 // using reflect. 18 // See doMapToMap. 19 func MapToMap(params interface{}, pointer interface{}, mapping ...map[string]string) error { 20 return Scan(params, pointer, mapping...) 21 } 22 23 // doMapToMap converts any map type variable `params` to another map type variable `pointer`. 24 // 25 // The parameter `params` can be any type of map, like: 26 // map[string]string, map[string]struct, map[string]*struct, reflect.Value, etc. 27 // 28 // The parameter `pointer` should be type of *map, like: 29 // map[int]string, map[string]struct, map[string]*struct, reflect.Value, etc. 30 // 31 // The optional parameter `mapping` is used for struct attribute to map key mapping, which makes 32 // sense only if the items of original map `params` is type struct. 33 func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) { 34 var ( 35 paramsRv reflect.Value 36 paramsKind reflect.Kind 37 keyToAttributeNameMapping map[string]string 38 ) 39 if len(mapping) > 0 { 40 keyToAttributeNameMapping = mapping[0] 41 } 42 if v, ok := params.(reflect.Value); ok { 43 paramsRv = v 44 } else { 45 paramsRv = reflect.ValueOf(params) 46 } 47 paramsKind = paramsRv.Kind() 48 if paramsKind == reflect.Ptr { 49 paramsRv = paramsRv.Elem() 50 paramsKind = paramsRv.Kind() 51 } 52 if paramsKind != reflect.Map { 53 return doMapToMap(Map(params), pointer, mapping...) 54 } 55 // Empty params map, no need continue. 56 if paramsRv.Len() == 0 { 57 return nil 58 } 59 var pointerRv reflect.Value 60 if v, ok := pointer.(reflect.Value); ok { 61 pointerRv = v 62 } else { 63 pointerRv = reflect.ValueOf(pointer) 64 } 65 pointerKind := pointerRv.Kind() 66 for pointerKind == reflect.Ptr { 67 pointerRv = pointerRv.Elem() 68 pointerKind = pointerRv.Kind() 69 } 70 if pointerKind != reflect.Map { 71 return gerror.NewCodef( 72 gcode.CodeInvalidParameter, 73 `destination pointer should be type of *map, but got: %s`, 74 pointerKind, 75 ) 76 } 77 defer func() { 78 // Catch the panic, especially the reflection operation panics. 79 if exception := recover(); exception != nil { 80 if v, ok := exception.(error); ok && gerror.HasStack(v) { 81 err = v 82 } else { 83 err = gerror.NewCodeSkipf(gcode.CodeInternalPanic, 1, "%+v", exception) 84 } 85 } 86 }() 87 var ( 88 paramsKeys = paramsRv.MapKeys() 89 pointerKeyType = pointerRv.Type().Key() 90 pointerValueType = pointerRv.Type().Elem() 91 pointerValueKind = pointerValueType.Kind() 92 dataMap = reflect.MakeMapWithSize(pointerRv.Type(), len(paramsKeys)) 93 ) 94 // Retrieve the true element type of target map. 95 if pointerValueKind == reflect.Ptr { 96 pointerValueKind = pointerValueType.Elem().Kind() 97 } 98 for _, key := range paramsKeys { 99 mapValue := reflect.New(pointerValueType).Elem() 100 switch pointerValueKind { 101 case reflect.Map, reflect.Struct: 102 if err = doStruct( 103 paramsRv.MapIndex(key).Interface(), mapValue, keyToAttributeNameMapping, "", 104 ); err != nil { 105 return err 106 } 107 default: 108 mapValue.Set( 109 reflect.ValueOf( 110 doConvert(doConvertInput{ 111 FromValue: paramsRv.MapIndex(key).Interface(), 112 ToTypeName: pointerValueType.String(), 113 ReferValue: mapValue, 114 Extra: nil, 115 }), 116 ), 117 ) 118 } 119 var mapKey = reflect.ValueOf( 120 doConvert(doConvertInput{ 121 FromValue: key.Interface(), 122 ToTypeName: pointerKeyType.Name(), 123 ReferValue: reflect.New(pointerKeyType).Elem().Interface(), 124 Extra: nil, 125 }), 126 ) 127 dataMap.SetMapIndex(mapKey, mapValue) 128 } 129 pointerRv.Set(dataMap) 130 return nil 131 }