package dynamicstruct import ( "errors" "fmt" "reflect" "time" ) type ( // Reader 通过反射读取结构体信息 Reader interface { // HasField 是否存在指定名称的字段 HasField(name string) bool // GetField 获取指定字段信息 GetField(name string) Field // GetAllFields 获取全部字段 GetAllFields() []Field // ToStruct 转结构体 ToStruct(value any) error // ToSliceOfReaders 转slice ToSliceOfReaders() []Reader // ToMapReaderOfReaders returns a map of Reader interfaces if value is representation ToMapReaderOfReaders() map[any]Reader // GetValue 获取输入的原始值 GetValue() any } // Field 对结构体字段的操作 Field interface { // Name 返回字段名称 Name() string // PointerInt int 指针 PointerInt() *int // Int int Int() int // PointerInt8 int8指针 PointerInt8() *int8 // Int8 int Int8() int8 // PointerInt16 int16指针 PointerInt16() *int16 // Int16 int16 Int16() int16 // PointerInt32 int32指针 PointerInt32() *int32 // Int32 int32 Int32() int32 // PointerInt64 int64指针 PointerInt64() *int64 // Int64 int64 Int64() int64 // PointerUint uint指针 PointerUint() *uint // Uint uint Uint() uint // PointerUint8 uint8指针 PointerUint8() *uint8 // Uint8 uint8 Uint8() uint8 // PointerUint16 uint16指针 PointerUint16() *uint16 // Uint16 uint16 Uint16() uint16 // PointerUint32 uint32指针 PointerUint32() *uint32 // Uint32 uint32 Uint32() uint32 // PointerUint64 uint64指针 PointerUint64() *uint64 // Uint64 uint64 Uint64() uint64 // PointerFloat32 float32指针 PointerFloat32() *float32 // Float32 float32 Float32() float32 // PointerFloat64 float64指针 PointerFloat64() *float64 // Float64 float64 Float64() float64 // PointerString string指针 PointerString() *string // String string String() string // PointerBool bool指针 PointerBool() *bool // Bool bool... Bool() bool // PointerTime time指针 PointerTime() *time.Time // Time time... Time() time.Time // Any any... Any() any } readImpl struct { fields map[string]fieldImpl value any } fieldImpl struct { field reflect.StructField value reflect.Value } ) // NewReader reads struct instance and provides instance of // Reader interface to give possibility to read all fields' values. func NewReader(value any) Reader { fields := map[string]fieldImpl{} valueOf := reflect.Indirect(reflect.ValueOf(value)) typeOf := valueOf.Type() if typeOf.Kind() == reflect.Struct { for i := 0; i < valueOf.NumField(); i++ { field := typeOf.Field(i) fields[field.Name] = fieldImpl{ field: field, value: valueOf.Field(i), } } } return readImpl{ fields: fields, value: value, } } func (r readImpl) HasField(name string) bool { _, ok := r.fields[name] return ok } func (r readImpl) GetField(name string) Field { if !r.HasField(name) { return nil } return r.fields[name] } func (r readImpl) GetAllFields() []Field { var fields []Field for _, field := range r.fields { fields = append(fields, field) } return fields } func (r readImpl) ToStruct(value any) error { valueOf := reflect.ValueOf(value) if valueOf.Kind() != reflect.Ptr || valueOf.IsNil() { return errors.New("ToStruct: expected a pointer as an argument") } valueOf = valueOf.Elem() typeOf := valueOf.Type() if valueOf.Kind() != reflect.Struct { return errors.New("ToStruct: expected a pointer to struct as an argument") } for i := 0; i < valueOf.NumField(); i++ { fieldType := typeOf.Field(i) fieldValue := valueOf.Field(i) original, ok := r.fields[fieldType.Name] if !ok { continue } if fieldValue.CanSet() && r.haveSameTypes(original.value.Type(), fieldValue.Type()) { fieldValue.Set(original.value) } } return nil } func (r readImpl) ToSliceOfReaders() []Reader { valueOf := reflect.Indirect(reflect.ValueOf(r.value)) typeOf := valueOf.Type() if typeOf.Kind() != reflect.Slice && typeOf.Kind() != reflect.Array { return nil } var readers []Reader for i := 0; i < valueOf.Len(); i++ { readers = append(readers, NewReader(valueOf.Index(i).Interface())) } return readers } func (r readImpl) ToMapReaderOfReaders() map[any]Reader { valueOf := reflect.Indirect(reflect.ValueOf(r.value)) typeOf := valueOf.Type() if typeOf.Kind() != reflect.Map { return nil } readers := map[any]Reader{} for _, keyValue := range valueOf.MapKeys() { readers[keyValue.Interface()] = NewReader(valueOf.MapIndex(keyValue).Interface()) } return readers } func (r readImpl) GetValue() any { return r.value } func (r readImpl) haveSameTypes(first reflect.Type, second reflect.Type) bool { if first.Kind() != second.Kind() { return false } switch first.Kind() { case reflect.Ptr: return r.haveSameTypes(first.Elem(), second.Elem()) case reflect.Struct: return first.PkgPath() == second.PkgPath() && first.Name() == second.Name() case reflect.Slice: return r.haveSameTypes(first.Elem(), second.Elem()) case reflect.Map: return r.haveSameTypes(first.Elem(), second.Elem()) && r.haveSameTypes(first.Key(), second.Key()) default: return first.Kind() == second.Kind() } } func (f fieldImpl) Name() string { return f.field.Name } func (f fieldImpl) PointerInt() *int { if f.value.IsNil() { return nil } value := f.Int() return &value } func (f fieldImpl) Int() int { return int(reflect.Indirect(f.value).Int()) } func (f fieldImpl) PointerInt8() *int8 { if f.value.IsNil() { return nil } value := f.Int8() return &value } func (f fieldImpl) Int8() int8 { return int8(reflect.Indirect(f.value).Int()) } func (f fieldImpl) PointerInt16() *int16 { if f.value.IsNil() { return nil } value := f.Int16() return &value } func (f fieldImpl) Int16() int16 { return int16(reflect.Indirect(f.value).Int()) } func (f fieldImpl) PointerInt32() *int32 { if f.value.IsNil() { return nil } value := f.Int32() return &value } func (f fieldImpl) Int32() int32 { return int32(reflect.Indirect(f.value).Int()) } func (f fieldImpl) PointerInt64() *int64 { if f.value.IsNil() { return nil } value := f.Int64() return &value } func (f fieldImpl) Int64() int64 { return reflect.Indirect(f.value).Int() } func (f fieldImpl) PointerUint() *uint { if f.value.IsNil() { return nil } value := f.Uint() return &value } func (f fieldImpl) Uint() uint { return uint(reflect.Indirect(f.value).Uint()) } func (f fieldImpl) PointerUint8() *uint8 { if f.value.IsNil() { return nil } value := f.Uint8() return &value } func (f fieldImpl) Uint8() uint8 { return uint8(reflect.Indirect(f.value).Uint()) } func (f fieldImpl) PointerUint16() *uint16 { if f.value.IsNil() { return nil } value := f.Uint16() return &value } func (f fieldImpl) Uint16() uint16 { return uint16(reflect.Indirect(f.value).Uint()) } func (f fieldImpl) PointerUint32() *uint32 { if f.value.IsNil() { return nil } value := f.Uint32() return &value } func (f fieldImpl) Uint32() uint32 { return uint32(reflect.Indirect(f.value).Uint()) } func (f fieldImpl) PointerUint64() *uint64 { if f.value.IsNil() { return nil } value := f.Uint64() return &value } func (f fieldImpl) Uint64() uint64 { return reflect.Indirect(f.value).Uint() } func (f fieldImpl) PointerFloat32() *float32 { if f.value.IsNil() { return nil } value := f.Float32() return &value } func (f fieldImpl) Float32() float32 { return float32(reflect.Indirect(f.value).Float()) } func (f fieldImpl) PointerFloat64() *float64 { if f.value.IsNil() { return nil } value := f.Float64() return &value } func (f fieldImpl) Float64() float64 { return reflect.Indirect(f.value).Float() } func (f fieldImpl) PointerString() *string { if f.value.IsNil() { return nil } value := f.String() return &value } func (f fieldImpl) String() string { return reflect.Indirect(f.value).String() } func (f fieldImpl) PointerBool() *bool { if f.value.IsNil() { return nil } value := f.Bool() return &value } func (f fieldImpl) Bool() bool { return reflect.Indirect(f.value).Bool() } func (f fieldImpl) PointerTime() *time.Time { if f.value.IsNil() { return nil } value := f.Time() return &value } func (f fieldImpl) Time() time.Time { value, ok := reflect.Indirect(f.value).Interface().(time.Time) if !ok { panic(fmt.Sprintf(`field "%s" is not instance of time.Time`, f.field.Name)) } return value } func (f fieldImpl) Any() any { return f.value.Interface() }