|
| 1 | +package filter |
| 2 | + |
| 3 | +import ( |
| 4 | + "reflect" |
| 5 | +) |
| 6 | + |
| 7 | +var fieldCacheVar fieldCache |
| 8 | + |
| 9 | +func init() { |
| 10 | + fieldCacheVar.maps = make(map[string]*field) |
| 11 | +} |
| 12 | + |
| 13 | +type fieldCache struct { |
| 14 | + maps map[string]*field |
| 15 | +} |
| 16 | +type field struct { |
| 17 | + index int //该字段所处结构体的索引位置 |
| 18 | + tag tag |
| 19 | + selectFields []*field |
| 20 | +} |
| 21 | + |
| 22 | +func newField(t tag, idx int) field { |
| 23 | + return field{ |
| 24 | + tag: t, |
| 25 | + index: idx, |
| 26 | + } |
| 27 | +} |
| 28 | + |
| 29 | +func getCacheKey(pkgInfo string, scene string, isSelect bool) string { |
| 30 | + mode := ".s" |
| 31 | + if !isSelect { |
| 32 | + mode = ".o" |
| 33 | + } |
| 34 | + return pkgInfo + "." + scene + mode |
| 35 | +} |
| 36 | +func (t *fieldNodeTree) parseAny2(key, scene string, valueOf reflect.Value, isSelect bool) { |
| 37 | + typeOf := valueOf.Type() |
| 38 | +TakePointerValue: //取指针的值 |
| 39 | + switch typeOf.Kind() { |
| 40 | + case reflect.Ptr: //如果是指针类型则取值重新判断类型 |
| 41 | + valueOf = valueOf.Elem() |
| 42 | + typeOf = typeOf.Elem() |
| 43 | + goto TakePointerValue |
| 44 | + case reflect.Interface: |
| 45 | + if !valueOf.IsNil() { |
| 46 | + valueOf = reflect.ValueOf(valueOf.Interface()) |
| 47 | + typeOf = valueOf.Type() |
| 48 | + goto TakePointerValue |
| 49 | + } else { |
| 50 | + parserNilInterface(t, key) |
| 51 | + } |
| 52 | + case reflect.Struct: |
| 53 | + parserStructCache(typeOf, valueOf, t, scene, key, isSelect) |
| 54 | + case reflect.Bool, |
| 55 | + reflect.String, |
| 56 | + reflect.Float64, reflect.Float32, |
| 57 | + reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int, |
| 58 | + reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: |
| 59 | + parserBaseType(valueOf, t, key) |
| 60 | + case reflect.Map: |
| 61 | + parserMap(valueOf, t, scene, isSelect) |
| 62 | + case reflect.Slice, reflect.Array: |
| 63 | + parserSliceOrArray(typeOf, valueOf, t, scene, key, isSelect) |
| 64 | + } |
| 65 | + |
| 66 | +} |
| 67 | + |
| 68 | +func parserStructCache(typeOf reflect.Type, valueOf reflect.Value, t *fieldNodeTree, scene string, key string, isSelect bool) { |
| 69 | + if valueOf.CanConvert(timeTypes) { //是time.Time类型或者底层是time.Time类型 |
| 70 | + t.Key = key |
| 71 | + t.Val = valueOf.Interface() |
| 72 | + return |
| 73 | + } |
| 74 | + if typeOf.NumField() == 0 { //如果是一个struct{}{}类型的字段或者是一个空的自定义结构体编码为{} |
| 75 | + t.Key = key |
| 76 | + t.Val = struct{}{} |
| 77 | + return |
| 78 | + } |
| 79 | + pkgInfo := typeOf.PkgPath() + "." + typeOf.Name() |
| 80 | + |
| 81 | + cacheKey := getCacheKey(pkgInfo, scene, isSelect) |
| 82 | + cacheField, ok := fieldCacheVar.maps[cacheKey] |
| 83 | + if !ok { |
| 84 | + |
| 85 | + var parentField *field |
| 86 | + if t.isRoot { |
| 87 | + //fieldCacheVar.maps[cacheKey] = &field{} |
| 88 | + parentField = new(field) |
| 89 | + fieldCacheVar.maps[cacheKey] = parentField |
| 90 | + } else { |
| 91 | + parentField = t.fieldCache |
| 92 | + } |
| 93 | + |
| 94 | + for i := 0; i < typeOf.NumField(); i++ { |
| 95 | + var tagInfo tagInfo |
| 96 | + tagInfo = getSelectTag(scene, pkgInfo, i, typeOf) |
| 97 | + if !isSelect { |
| 98 | + tagInfo = getOmitTag(scene, pkgInfo, i, typeOf) |
| 99 | + } |
| 100 | + |
| 101 | + if tagInfo.omit { |
| 102 | + continue |
| 103 | + } |
| 104 | + tag := tagInfo.tag |
| 105 | + if tag.IsOmitField || !tag.IsSelect { |
| 106 | + continue |
| 107 | + } |
| 108 | + isAnonymous := typeOf.Field(i).Anonymous && tag.IsAnonymous ////什么时候才算真正的匿名字段? Book中Article才算匿名结构体 |
| 109 | + tag.IsAnonymous = isAnonymous |
| 110 | + fieldCache := newField(tag, i) |
| 111 | + fieldEl, ok1 := fieldCacheVar.maps[cacheKey] |
| 112 | + if ok1 { |
| 113 | + fieldEl.selectFields = append(fieldEl.selectFields, &fieldCache) |
| 114 | + //fieldCacheVar.maps[cacheKey].selectFields = append(fieldCacheVar.maps[cacheKey].selectFields, &fieldCache) |
| 115 | + } |
| 116 | + |
| 117 | + tree := &fieldNodeTree{ |
| 118 | + Key: tag.UseFieldName, |
| 119 | + ParentNode: t, |
| 120 | + IsAnonymous: isAnonymous, |
| 121 | + Tag: tag, |
| 122 | + fieldCache: &fieldCache, |
| 123 | + } |
| 124 | + value := valueOf.Field(i) |
| 125 | + if tag.Function != "" { |
| 126 | + function := valueOf.MethodByName(tag.Function) |
| 127 | + if !function.IsValid() { |
| 128 | + if valueOf.CanAddr() { |
| 129 | + function = valueOf.Addr().MethodByName(tag.Function) |
| 130 | + } |
| 131 | + } |
| 132 | + if function.IsValid() { |
| 133 | + values := function.Call([]reflect.Value{}) |
| 134 | + if len(values) != 0 { |
| 135 | + value = values[0] |
| 136 | + } |
| 137 | + } |
| 138 | + } |
| 139 | + if value.Kind() == reflect.Ptr { |
| 140 | + TakeFieldValue: |
| 141 | + if value.Kind() == reflect.Ptr { |
| 142 | + if value.IsNil() { |
| 143 | + if tag.Omitempty { |
| 144 | + continue |
| 145 | + } |
| 146 | + tree.IsNil = true |
| 147 | + t.AddChild(tree) |
| 148 | + continue |
| 149 | + } else { |
| 150 | + value = value.Elem() |
| 151 | + goto TakeFieldValue |
| 152 | + } |
| 153 | + } |
| 154 | + } else { |
| 155 | + if tag.Omitempty { |
| 156 | + if value.IsZero() { //为零值忽略 |
| 157 | + continue |
| 158 | + } |
| 159 | + } |
| 160 | + } |
| 161 | + |
| 162 | + tree.parseAny2(tag.UseFieldName, scene, value, isSelect) |
| 163 | + |
| 164 | + if t.IsAnonymous { |
| 165 | + t.AnonymousAddChild(tree) |
| 166 | + } else { |
| 167 | + t.AddChild(tree) |
| 168 | + } |
| 169 | + } |
| 170 | + } else { //说明缓存取到 |
| 171 | + for i := 0; i < len(cacheField.selectFields); i++ { |
| 172 | + fieldInfo := cacheField.selectFields[i] |
| 173 | + tag := fieldInfo.tag |
| 174 | + tree := &fieldNodeTree{ |
| 175 | + Key: tag.UseFieldName, |
| 176 | + ParentNode: t, |
| 177 | + IsAnonymous: tag.IsAnonymous, |
| 178 | + Tag: tag, |
| 179 | + fieldCache: fieldInfo, |
| 180 | + } |
| 181 | + value := valueOf.Field(fieldInfo.index) |
| 182 | + if tag.Function != "" { |
| 183 | + function := valueOf.MethodByName(tag.Function) |
| 184 | + if !function.IsValid() { |
| 185 | + if valueOf.CanAddr() { |
| 186 | + function = valueOf.Addr().MethodByName(tag.Function) |
| 187 | + } |
| 188 | + } |
| 189 | + if function.IsValid() { |
| 190 | + values := function.Call([]reflect.Value{}) |
| 191 | + if len(values) != 0 { |
| 192 | + value = values[0] |
| 193 | + } |
| 194 | + } |
| 195 | + } |
| 196 | + if value.Kind() == reflect.Ptr { |
| 197 | + TakeFieldValue1: |
| 198 | + if value.Kind() == reflect.Ptr { |
| 199 | + if value.IsNil() { |
| 200 | + if tag.Omitempty { |
| 201 | + continue |
| 202 | + } |
| 203 | + tree.IsNil = true |
| 204 | + t.AddChild(tree) |
| 205 | + continue |
| 206 | + } else { |
| 207 | + value = value.Elem() |
| 208 | + goto TakeFieldValue1 |
| 209 | + } |
| 210 | + } |
| 211 | + } else { |
| 212 | + if tag.Omitempty { |
| 213 | + if value.IsZero() { //为零值忽略 |
| 214 | + continue |
| 215 | + } |
| 216 | + } |
| 217 | + } |
| 218 | + |
| 219 | + tree.parseAny2(tag.UseFieldName, scene, value, isSelect) |
| 220 | + |
| 221 | + if t.IsAnonymous { |
| 222 | + t.AnonymousAddChild(tree) |
| 223 | + } else { |
| 224 | + t.AddChild(tree) |
| 225 | + } |
| 226 | + } |
| 227 | + } |
| 228 | + |
| 229 | + if t.Children == nil && !t.IsAnonymous { |
| 230 | + t.Val = struct{}{} //这样表示返回{} |
| 231 | + } |
| 232 | + |
| 233 | +} |
0 commit comments