| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- package tag
- import (
- "git.sxidc.com/go-framework/baize/infrastructure/logger"
- "git.sxidc.com/go-tools/utils/strutils"
- "git.sxidc.com/service-supports/fserr"
- "reflect"
- "strings"
- "time"
- )
- func AssignTo[F any, T any](from F) T {
- var zero T
- assign, err := ParseAssignTag(from)
- if err != nil {
- logger.GetInstance().Error(err)
- return zero
- }
- retType := reflect.TypeOf(zero)
- retValue := reflect.New(retType).Elem()
- return retValue.Interface()
- }
- const (
- assignDefaultStringSliceSeparator = "::"
- assignTagPartSeparator = ";"
- assignTagPartKeyValueSeparator = ":"
- )
- const (
- assignTagKey = "assign"
- assignIgnore = "-"
- assignToField = "toField"
- assignParseTime = "parseTime"
- assignFormatTime = "formatTime"
- assignJoinWith = "joinWith"
- assignSplitWith = "splitWith"
- assignTrim = "trim"
- assignTrimLeft = "trimLeft"
- assignTrimRight = "trimRight"
- )
- type Assign struct {
- AssignElement map[string]any
- }
- type AssignElement struct {
- ToField string
- ParseTime string
- FormatTime string
- JoinWith string
- SplitWith string
- Trim string
- TrimLeft string
- TrimRight string
- // 原字段的反射结构
- OriginFieldType reflect.Type
- OriginFieldValue reflect.Value
- // 值类型的反射结构
- FieldTypeElem reflect.Type
- FieldValueElem reflect.Value
- }
- func ParseAssignTag(from any) (*Assign, error) {
- if from == nil {
- return nil, fserr.New("没有传递结构或结构指针")
- }
- fromType := reflect.TypeOf(from)
- if fromType.Kind() != reflect.Ptr && fromType.Kind() != reflect.Struct {
- return nil, fserr.New("参数不是结构或结构指针")
- }
- if fromType.Kind() == reflect.Ptr && fromType.Elem().Kind() != reflect.Struct {
- return nil, fserr.New("参数不是结构或结构指针")
- }
- fromValue := reflect.ValueOf(from)
- fromElemValue := fromValue
- if fromType.Kind() == reflect.Ptr {
- fromElemValue = fromValue.Elem()
- }
- assign := new(Assign)
- assign.AssignElement = make(map[string]any)
- for i := 0; i < fromElemValue.NumField(); i++ {
- field := fromType.Field(i)
- fieldValue := fromElemValue.Field(i)
- // 零值,不用赋值
- if !fieldValue.IsValid() {
- continue
- }
- element, err := parseSqlMappingElement(field, fieldValue)
- if err != nil {
- return nil, err
- }
- if element == nil {
- continue
- }
- assign.AssignElement[field.Name] = element
- }
- return assign, nil
- }
- func parseSqlMappingElement(field reflect.StructField, fieldValue reflect.Value) (any, error) {
- assignTag := field.Tag.Get(assignTagKey)
- if assignTag == assignIgnore {
- return nil, nil
- }
- fieldValueElemType := field.Type
- if field.Type.Kind() == reflect.Ptr {
- fieldValueElemType = field.Type.Elem()
- }
- fieldValueElem := fieldValue
- if fieldValue.Kind() == reflect.Ptr {
- fieldValueElem = fieldValue.Elem()
- }
- if fieldValueElemType.Kind() == reflect.Struct && fieldValueElemType != reflect.TypeOf(time.Time{}) {
- return ParseAssignTag(fieldValueElem.Interface())
- }
- element := &AssignElement{
- ToField: field.Name,
- ParseTime: time.DateTime,
- FormatTime: time.DateTime,
- JoinWith: assignDefaultStringSliceSeparator,
- SplitWith: assignDefaultStringSliceSeparator,
- Trim: "",
- TrimLeft: "",
- TrimRight: "",
- OriginFieldType: field.Type,
- OriginFieldValue: fieldValue,
- FieldTypeElem: fieldValueElemType,
- FieldValueElem: fieldValueElem,
- }
- if strutils.IsStringEmpty(assignTag) {
- return element, nil
- }
- assignParts := strings.Split(assignTag, assignTagPartSeparator)
- if assignParts != nil || len(assignParts) != 0 {
- for _, assignPart := range assignParts {
- assignPartKeyValue := strings.SplitN(strings.TrimSpace(assignPart), assignTagPartKeyValueSeparator, 2)
- if assignPartKeyValue != nil && len(assignPartKeyValue) == 2 && strutils.IsStringNotEmpty(assignPartKeyValue[1]) {
- // 可以支持' ' ',获取到'字符
- assignPartKeyValue[1] = strings.TrimSpace(strings.Trim(assignPartKeyValue[1], "'"))
- }
- switch assignPartKeyValue[0] {
- case assignToField:
- element.ToField = assignPartKeyValue[1]
- case assignParseTime:
- if fieldValueElemType.Elem().Kind() != reflect.String {
- return nil, fserr.New(assignParseTime + "应该添加在string字段上")
- }
- element.ParseTime = assignPartKeyValue[1]
- case assignFormatTime:
- if fieldValueElemType.Elem().Kind() != reflect.Struct && fieldValueElemType != reflect.TypeOf(time.Time{}) {
- return nil, fserr.New(assignFormatTime + "应该添加在time.Time字段上")
- }
- element.FormatTime = assignPartKeyValue[1]
- case assignJoinWith:
- if strutils.IsStringEmpty(assignPartKeyValue[1]) {
- return nil, fserr.New(assignJoinWith + "没有赋值分隔符")
- }
- if fieldValueElemType.Kind() != reflect.Slice || fieldValueElemType.Elem().Kind() != reflect.String {
- return nil, fserr.New(assignJoinWith + "应该添加在[]string字段上")
- }
- element.JoinWith = assignPartKeyValue[1]
- case assignSplitWith:
- if strutils.IsStringEmpty(assignPartKeyValue[1]) {
- return nil, fserr.New(assignSplitWith + "没有赋值分隔符")
- }
- if fieldValueElemType.Elem().Kind() != reflect.String {
- return nil, fserr.New(assignSplitWith + "应该添加在string字段上")
- }
- element.SplitWith = assignPartKeyValue[1]
- case assignTrim:
- if fieldValueElemType.Elem().Kind() != reflect.String {
- return nil, fserr.New(assignTrim + "应该添加在string字段上")
- }
- element.Trim = assignPartKeyValue[1]
- case assignTrimLeft:
- if fieldValueElemType.Elem().Kind() != reflect.String {
- return nil, fserr.New(assignTrimLeft + "应该添加在string字段上")
- }
- element.TrimLeft = assignPartKeyValue[1]
- case assignTrimRight:
- if fieldValueElemType.Elem().Kind() != reflect.String {
- return nil, fserr.New(assignTrimRight + "应该添加在string字段上")
- }
- element.TrimRight = assignPartKeyValue[1]
- default:
- continue
- }
- }
- }
- return element, nil
- }
|