github.com/suiyunonghen/DxCommonLib@v0.5.3/reflect.go (about) 1 /* 2 反射相关的处理 3 Autor: 不得闲 4 QQ:75492895 5 */ 6 7 package DxCommonLib 8 9 import ( 10 "reflect" 11 "strconv" 12 ) 13 14 //IsSimpleCopyKind 是否是简单的可copy的类型 15 func IsSimpleCopyKind(kind reflect.Kind) bool { 16 switch kind { 17 case reflect.String, reflect.Int, reflect.Int64, reflect.Int8, reflect.Int16, reflect.Int32, 18 reflect.Uint, reflect.Uint64, reflect.Uint8, reflect.Uint16, reflect.Uint32, 19 reflect.Float32, reflect.Float64, reflect.Bool: 20 return true 21 default: 22 return false 23 } 24 } 25 26 /*CanConvertStructField 27 field1->是否能够 匹配field2字段 28 */ 29 func CanConvertStructField(field1, field2 *reflect.StructField) bool { 30 if field1.Type != field2.Type { 31 f1Kind := field1.Type.Kind() 32 if field1.Type.Kind() == reflect.Interface { 33 return false 34 } 35 f2Kind := field2.Type.Kind() 36 switch f1Kind { 37 case reflect.Map: 38 if f2Kind != reflect.Map && f2Kind != reflect.Struct { 39 return false 40 } 41 case reflect.Struct: 42 if f2Kind != reflect.Map && f2Kind != reflect.Struct { 43 return false 44 } 45 if f2Kind == reflect.Map && field2.Type.Key().Kind() != reflect.String { 46 return false 47 } 48 case reflect.Slice: 49 if f2Kind == reflect.Slice { 50 f1VKind := field1.Type.Elem().Kind() 51 f2VKind := field2.Type.Elem().Kind() 52 if f1VKind != f2VKind && f2VKind != reflect.Interface { 53 return false 54 } 55 } 56 default: 57 return false 58 } 59 } 60 if field1.Name == field2.Name { 61 return true 62 } 63 //再判定tag 64 tagMap1 := ParseStructTag(string(field1.Tag)) 65 if tagMap1 != nil { 66 for _, v := range tagMap1 { 67 if v == field2.Name { 68 return true 69 } 70 } 71 } 72 tagMap2 := ParseStructTag(string(field2.Tag)) 73 if tagMap2 != nil { 74 for _, v := range tagMap2 { 75 if v == field1.Name { 76 return true 77 } 78 } 79 } 80 if tagMap1 != nil && tagMap2 != nil { 81 for _, v := range tagMap1 { 82 for _, v2 := range tagMap2 { 83 if v == v2 { 84 return true 85 } 86 } 87 } 88 } 89 return false 90 } 91 92 //ParseStructTag 后续可以缓存起来 93 func ParseStructTag(tag string) map[string]string { 94 var result map[string]string 95 for tag != "" { 96 // Skip leading space. 97 i := 0 98 for i < len(tag) && tag[i] == ' ' { 99 i++ 100 } 101 tag = tag[i:] 102 if tag == "" { 103 break 104 } 105 106 // Scan to colon. A space, a quote or a control character is a syntax error. 107 // Strictly speaking, control chars include the range [0x7f, 0x9f], not just 108 // [0x00, 0x1f], but in practice, we ignore the multi-byte control characters 109 // as it is simpler to inspect the tag's bytes than the tag's runes. 110 i = 0 111 for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f { 112 i++ 113 } 114 if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' { 115 break 116 } 117 name := string(tag[:i]) 118 tag = tag[i+1:] 119 120 // Scan quoted string to find value. 121 i = 1 122 for i < len(tag) && tag[i] != '"' { 123 if tag[i] == '\\' { 124 i++ 125 } 126 i++ 127 } 128 if i >= len(tag) { 129 break 130 } 131 qvalue := string(tag[:i+1]) 132 tag = tag[i+1:] 133 value, err := strconv.Unquote(qvalue) 134 if err != nil { 135 result = nil 136 break 137 } 138 if result == nil { 139 result = make(map[string]string) 140 } 141 result[name] = value 142 } 143 return result 144 } 145 146 /*CanKeyMatchStructField 147 key是否匹配field 148 */ 149 func CanKeyMatchStructField(key string, field *reflect.StructField) bool { 150 if key == field.Name { 151 return true 152 } 153 tagMap := ParseStructTag(string(field.Tag)) 154 if tagMap != nil { 155 for _, v := range tagMap { 156 if v == key { 157 return true 158 } 159 } 160 } 161 return false 162 }