github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/ztype/struct.go (about) 1 package ztype 2 3 import ( 4 "reflect" 5 "strings" 6 7 "github.com/sohaha/zlsgo/zreflect" 8 ) 9 10 type ( 11 StruBuilder struct { 12 key reflect.Type 13 fields map[string]*StruField 14 fieldKeys []string 15 typ int 16 } 17 StruField struct { 18 typ interface{} 19 tag string 20 } 21 ) 22 23 const ( 24 typeStruct = iota 25 typeMapStruct 26 typeSliceStruct 27 ) 28 29 func NewStruct() *StruBuilder { 30 return &StruBuilder{ 31 typ: typeStruct, 32 fields: map[string]*StruField{}, 33 } 34 } 35 36 func NewMapStruct(key interface{}) *StruBuilder { 37 var k reflect.Type 38 if v, ok := key.(reflect.Type); ok { 39 k = v 40 } else { 41 k = reflect.TypeOf(key) 42 } 43 return &StruBuilder{ 44 typ: typeMapStruct, 45 key: k, 46 fields: map[string]*StruField{}, 47 } 48 } 49 50 func NewSliceStruct() *StruBuilder { 51 return &StruBuilder{ 52 typ: typeSliceStruct, 53 fields: map[string]*StruField{}, 54 } 55 } 56 57 func (b *StruBuilder) Copy(v *StruBuilder) *StruBuilder { 58 typ := b.typ 59 val := *v 60 *b = val 61 b.typ = typ 62 return b 63 } 64 65 func (b *StruBuilder) Merge(values ...interface{}) *StruBuilder { 66 for _, value := range values { 67 valueOf := reflect.Indirect(zreflect.ValueOf(value)) 68 typeOf := valueOf.Type() 69 for i := 0; i < valueOf.NumField(); i++ { 70 fval := valueOf.Field(i) 71 ftyp := typeOf.Field(i) 72 b.AddField(ftyp.Name, fval.Interface(), string(ftyp.Tag)) 73 } 74 } 75 76 return b 77 } 78 79 // func (b *StruBuilder) AddFunc(name string, fieldType interface{}, tag ...string) *StruBuilder { 80 // reflect.MakeFunc() 81 // return b 82 // } 83 84 func (b *StruBuilder) AddField(name string, fieldType interface{}, tag ...string) *StruBuilder { 85 var t string 86 if len(tag) > 0 { 87 t = strings.Join(tag, " ") 88 } 89 if b.typ == typeStruct { 90 nkey := make([]string, 0, len(b.fieldKeys)) 91 for i := range b.fieldKeys { 92 if b.fieldKeys[i] != name { 93 nkey = append(nkey, b.fieldKeys[i]) 94 } 95 } 96 b.fieldKeys = append(nkey, name) 97 } 98 b.fields[name] = &StruField{ 99 typ: fieldType, 100 tag: t, 101 } 102 return b 103 } 104 105 func (b *StruBuilder) RemoveField(name string) *StruBuilder { 106 delete(b.fields, name) 107 if b.typ == typeStruct { 108 nkey := make([]string, 0, len(b.fieldKeys)) 109 for i := range b.fieldKeys { 110 if b.fieldKeys[i] != name { 111 nkey = append(nkey, b.fieldKeys[i]) 112 } 113 } 114 b.fieldKeys = nkey 115 } 116 return b 117 } 118 119 func (b *StruBuilder) HasField(name string) bool { 120 _, ok := b.fields[name] 121 return ok 122 } 123 124 func (b *StruBuilder) GetField(name string) *StruField { 125 if !b.HasField(name) { 126 return nil 127 } 128 return b.fields[name] 129 } 130 131 func (b *StruBuilder) Interface() interface{} { 132 return b.Value().Interface() 133 } 134 135 func (b *StruBuilder) Type() reflect.Type { 136 var fields []reflect.StructField 137 fn := func(name string, field *StruField) { 138 var t reflect.Type 139 switch v := field.typ.(type) { 140 case *StruBuilder: 141 t = v.Type() 142 case reflect.Type: 143 t = v 144 default: 145 t = reflect.TypeOf(field.typ) 146 } 147 148 fields = append(fields, reflect.StructField{ 149 Name: name, 150 Type: t, 151 Tag: reflect.StructTag(field.tag), 152 }) 153 } 154 if b.typ == typeStruct { 155 for i := range b.fieldKeys { 156 name := b.fieldKeys[i] 157 if field, ok := b.fields[name]; ok { 158 fn(name, field) 159 } 160 } 161 } else { 162 for name := range b.fields { 163 field := b.fields[name] 164 fn(name, field) 165 } 166 } 167 168 typ := reflect.StructOf(fields) 169 170 switch b.typ { 171 case typeSliceStruct: 172 return reflect.SliceOf(typ) 173 case typeMapStruct: 174 return reflect.MapOf(b.key, typ) 175 default: 176 return typ 177 } 178 } 179 180 func (b *StruBuilder) Value() reflect.Value { 181 return reflect.New(b.Type()) 182 } 183 184 func (f *StruField) SetType(typ interface{}) *StruField { 185 f.typ = typ 186 return f 187 } 188 189 func (f *StruField) SetTag(tag string) *StruField { 190 f.tag = tag 191 return f 192 }