package assign import ( "git.sxidc.com/go-tools/utils/reflectutils" "git.sxidc.com/go-tools/utils/strutils" "github.com/pkg/errors" "reflect" "strings" "time" ) func DefaultUsage(from any, to any) error { return UseTag(from, to, func(fromFieldName string, fromFieldElemValue reflect.Value, retFieldElementValue reflect.Value, tag *Tag) error { if fromFieldElemValue.IsZero() { return nil } return defaultCallback(fromFieldElemValue, retFieldElementValue, tag) }) } func defaultCallback(fromFieldElemValue reflect.Value, toFieldElemValue reflect.Value, tag *Tag) error { fromKind := reflectutils.GroupValueKind(fromFieldElemValue) toKind := reflectutils.GroupValueKind(toFieldElemValue) var fromAny any switch fromKind { case reflect.Struct: // time.Time类型的结构,接收字段是string类型,使用FormatTime的格式转换 if reflectutils.IsValueTime(fromFieldElemValue) && toKind == reflect.String { fromString := fromFieldElemValue.Interface().(time.Time).Format(tag.TimeLayout) fromAny = trimFromString(fromString, tag) break } // 不是time.Time类型的结构,接收字段是结构,执行结构到结构字段的赋值 if !reflectutils.IsValueTime(fromFieldElemValue) && toKind == reflect.Struct { return parseTag(fromFieldElemValue, &toFieldElemValue, func(fromFieldName string, fromFieldElemValue reflect.Value, toFieldElementValue reflect.Value, tag *Tag) error { return defaultCallback(fromFieldElemValue, toFieldElementValue, tag) }) } // 直接将整个结构进行字段赋值 fromAny = fromFieldElemValue.Interface() case reflect.Slice: fromFieldElementElemType := reflectutils.PointerTypeElem(fromFieldElemValue.Type().Elem()) if fromFieldElementElemType.Kind() == reflect.String && toKind == reflect.String { stringSlice := make([]string, 0) for i := 0; i < fromFieldElemValue.Len(); i++ { stringSlice = append(stringSlice, reflectutils.PointerValueElem(fromFieldElemValue.Index(i)).Interface().(string)) } fromString := strings.Join(stringSlice, tag.JoinWith) fromAny = trimFromString(fromString, tag) break } if fromFieldElementElemType.Kind() == reflect.Struct && reflectutils.IsTypeTime(fromFieldElementElemType) && toFieldElemValue.Type().Kind() == reflect.Slice && reflectutils.PointerTypeElem(toFieldElemValue.Type().Elem()).Kind() == reflect.String { stringSlice := make([]string, 0) for i := 0; i < fromFieldElemValue.Len(); i++ { fromString := reflectutils.PointerValueElem(fromFieldElemValue.Index(i)).Interface().(time.Time).Format(tag.TimeLayout) stringSlice = append(stringSlice, trimFromString(fromString, tag)) } fromAny = stringSlice break } if fromFieldElementElemType.Kind() == reflect.String && toFieldElemValue.Type().Kind() == reflect.Slice && reflectutils.PointerTypeElem(toFieldElemValue.Type().Elem()).Kind() == reflect.Struct && reflectutils.IsTypeTime(reflectutils.PointerTypeElem(toFieldElemValue.Type().Elem())) { timeSlice := make([]time.Time, 0) for i := 0; i < fromFieldElemValue.Len(); i++ { timeParsed, err := time.ParseInLocation(tag.TimeLayout, reflectutils.PointerValueElem(fromFieldElemValue.Index(i)).Interface().(string), time.Local) if err != nil { return err } timeSlice = append(timeSlice, timeParsed) } fromAny = timeSlice break } fromAny = fromFieldElemValue.Interface() case reflect.String: fromString := fromFieldElemValue.String() if reflectutils.IsValueTime(toFieldElemValue) { toTimeField, err := time.ParseInLocation(tag.TimeLayout, fromString, time.Local) if err != nil { return err } fromAny = toTimeField break } if reflectutils.IsSliceValueOf(toFieldElemValue, reflect.String) { fromAny = strings.Split(fromString, tag.SplitWith) break } fromAny = trimFromString(fromString, tag) default: fromAny = fromFieldElemValue.Interface() } err := assignTo(toKind, fromAny, toFieldElemValue) if err != nil { return err } return nil } func assignTo(toKind reflect.Kind, fromAny any, toFieldElemValue reflect.Value) error { switch toKind { case reflect.Int64: return reflectutils.AssignInt64Value(fromAny, toFieldElemValue) case reflect.Uint64: return reflectutils.AssignUint64Value(fromAny, toFieldElemValue) case reflect.Float64: return reflectutils.AssignFloat64Value(fromAny, toFieldElemValue) case reflect.Bool: return reflectutils.AssignBoolValue(fromAny, toFieldElemValue) case reflect.String: return reflectutils.AssignStringValue(fromAny, toFieldElemValue) case reflect.Slice: return assignSlice(fromAny, toFieldElemValue) default: toFieldElemValue.Set(reflect.ValueOf(fromAny)) return nil } } func trimFromString(fromString string, tag *Tag) string { if strutils.IsStringNotEmpty(tag.Trim) { return strings.Trim(fromString, tag.Trim) } else { if strutils.IsStringNotEmpty(tag.TrimPrefix) { return strings.TrimPrefix(fromString, tag.TrimPrefix) } if strutils.IsStringNotEmpty(tag.TrimSuffix) { return strings.TrimSuffix(fromString, tag.TrimSuffix) } } return fromString } func assignSlice(fromAny any, toFieldElemValue reflect.Value) error { fromElemValue := reflectutils.PointerValueElem(reflect.ValueOf(fromAny)) if fromElemValue.Kind() != reflect.Slice { return errors.New("不支持的操作:试图将非slice类型字段赋值给slice类型字段") } if toFieldElemValue.Kind() != reflect.Slice { return errors.New("不支持的操作:试图将slice类型字段赋值给非slice类型字段") } // 构造slice sliceValue := reflect.MakeSlice(toFieldElemValue.Type(), 0, 0) // 遍历from slice for i := 0; i < fromElemValue.Len(); i++ { // 获取from slice中元素的Value fromElementValue := fromElemValue.Index(i) // 获取from slice中元素的ElemValue fromElementElemValue := reflectutils.PointerValueElem(fromElementValue) // 获取from slice中元素是nil指针 if fromElementValue.Kind() == reflect.Pointer && fromElementValue.IsNil() { fromElementElemValue = reflect.New(fromElementElemValue.Type()).Elem() } if fromElementElemValue.Kind() == reflect.Slice { if toFieldElemValue.Type().Elem().Kind() != reflect.Slice { return errors.New("不支持的操作:试图将slice类型字段赋值给非slice类型字段") } toSliceElementValue := reflect.MakeSlice(toFieldElemValue.Type().Elem(), 0, 0) err := assignSlice(fromElementElemValue.Interface(), toSliceElementValue) if err != nil { return err } for j := 0; j < toSliceElementValue.Len(); j++ { if toFieldElemValue.Type().Elem().Kind() == reflect.Pointer { sliceValue = reflect.Append(sliceValue, toSliceElementValue.Index(i).Addr()) } else { sliceValue = reflect.Append(sliceValue, toSliceElementValue.Index(i)) } } continue } var toElementElemValue reflect.Value if toFieldElemValue.Type().Elem().Kind() == reflect.Pointer { if toFieldElemValue.Type().Elem().Elem().Kind() == fromElementElemValue.Kind() && toFieldElemValue.Type().Elem().Elem().String() == fromElementElemValue.Type().String() { toElementElemValue = fromElementElemValue } else { toElementElemValue = reflect.New(toFieldElemValue.Type().Elem().Elem()).Elem() } } else { if toFieldElemValue.Type().Elem().Kind() == fromElementElemValue.Kind() && toFieldElemValue.Type().Elem().String() == fromElementElemValue.String() { toElementElemValue = fromElementValue } else { toElementElemValue = reflect.New(toFieldElemValue.Type().Elem()).Elem() } } if fromElementElemValue.Kind() == reflect.Struct { if reflectutils.IsValueTime(fromElementElemValue) { if !reflectutils.IsValueTime(toElementElemValue) { return errors.New("无法从time.Time赋值到不是time.Time的结构") } if toElementElemValue.Type().Kind() == reflect.Pointer { toElementElemValue.Set(fromElementElemValue.Addr()) } else { toElementElemValue.Set(fromElementElemValue) } } else { err := DefaultUsage(fromElementElemValue.Interface(), toElementElemValue.Addr().Interface()) if err != nil { return err } } if toFieldElemValue.Type().Elem().Kind() == reflect.Pointer { sliceValue = reflect.Append(sliceValue, toElementElemValue.Addr()) } else { sliceValue = reflect.Append(sliceValue, toElementElemValue) } continue } toElementKind := reflectutils.GroupValueKind(toElementElemValue) err := assignTo(toElementKind, fromElementElemValue.Interface(), toElementElemValue) if err != nil { return err } if toFieldElemValue.Type().Elem().Kind() == reflect.Pointer { sliceValue = reflect.Append(sliceValue, toElementElemValue.Addr()) } else { sliceValue = reflect.Append(sliceValue, toElementElemValue) } } toFieldElemValue.Set(sliceValue) return nil }