github.com/suiyunonghen/DxCommonLib@v0.5.3/reflect.go (about)

     1  /*
     2    反射相关的处理
     3    Autor: 不得闲
     4    QQ:75492895
     5  */
     6  
     7  package DxCommonLib
     8  
     9  import (
    10  	"reflect"
    11  	"strconv"
    12  )
    13  
    14  //IsSimpleCopyKind 是否是简单的可copy的类型
    15  func IsSimpleCopyKind(kind reflect.Kind) bool {
    16  	switch kind {
    17  	case reflect.String, reflect.Int, reflect.Int64, reflect.Int8, reflect.Int16, reflect.Int32,
    18  		reflect.Uint, reflect.Uint64, reflect.Uint8, reflect.Uint16, reflect.Uint32,
    19  		reflect.Float32, reflect.Float64, reflect.Bool:
    20  		return true
    21  	default:
    22  		return false
    23  	}
    24  }
    25  
    26  /*CanConvertStructField
    27  field1->是否能够 匹配field2字段
    28  */
    29  func CanConvertStructField(field1, field2 *reflect.StructField) bool {
    30  	if field1.Type != field2.Type {
    31  		f1Kind := field1.Type.Kind()
    32  		if field1.Type.Kind() == reflect.Interface {
    33  			return false
    34  		}
    35  		f2Kind := field2.Type.Kind()
    36  		switch f1Kind {
    37  		case reflect.Map:
    38  			if f2Kind != reflect.Map && f2Kind != reflect.Struct {
    39  				return false
    40  			}
    41  		case reflect.Struct:
    42  			if f2Kind != reflect.Map && f2Kind != reflect.Struct {
    43  				return false
    44  			}
    45  			if f2Kind == reflect.Map && field2.Type.Key().Kind() != reflect.String {
    46  				return false
    47  			}
    48  		case reflect.Slice:
    49  			if f2Kind == reflect.Slice {
    50  				f1VKind := field1.Type.Elem().Kind()
    51  				f2VKind := field2.Type.Elem().Kind()
    52  				if f1VKind != f2VKind && f2VKind != reflect.Interface {
    53  					return false
    54  				}
    55  			}
    56  		default:
    57  			return false
    58  		}
    59  	}
    60  	if field1.Name == field2.Name {
    61  		return true
    62  	}
    63  	//再判定tag
    64  	tagMap1 := ParseStructTag(string(field1.Tag))
    65  	if tagMap1 != nil {
    66  		for _, v := range tagMap1 {
    67  			if v == field2.Name {
    68  				return true
    69  			}
    70  		}
    71  	}
    72  	tagMap2 := ParseStructTag(string(field2.Tag))
    73  	if tagMap2 != nil {
    74  		for _, v := range tagMap2 {
    75  			if v == field1.Name {
    76  				return true
    77  			}
    78  		}
    79  	}
    80  	if tagMap1 != nil && tagMap2 != nil {
    81  		for _, v := range tagMap1 {
    82  			for _, v2 := range tagMap2 {
    83  				if v == v2 {
    84  					return true
    85  				}
    86  			}
    87  		}
    88  	}
    89  	return false
    90  }
    91  
    92  //ParseStructTag 后续可以缓存起来
    93  func ParseStructTag(tag string) map[string]string {
    94  	var result map[string]string
    95  	for tag != "" {
    96  		// Skip leading space.
    97  		i := 0
    98  		for i < len(tag) && tag[i] == ' ' {
    99  			i++
   100  		}
   101  		tag = tag[i:]
   102  		if tag == "" {
   103  			break
   104  		}
   105  
   106  		// Scan to colon. A space, a quote or a control character is a syntax error.
   107  		// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
   108  		// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
   109  		// as it is simpler to inspect the tag's bytes than the tag's runes.
   110  		i = 0
   111  		for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
   112  			i++
   113  		}
   114  		if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
   115  			break
   116  		}
   117  		name := string(tag[:i])
   118  		tag = tag[i+1:]
   119  
   120  		// Scan quoted string to find value.
   121  		i = 1
   122  		for i < len(tag) && tag[i] != '"' {
   123  			if tag[i] == '\\' {
   124  				i++
   125  			}
   126  			i++
   127  		}
   128  		if i >= len(tag) {
   129  			break
   130  		}
   131  		qvalue := string(tag[:i+1])
   132  		tag = tag[i+1:]
   133  		value, err := strconv.Unquote(qvalue)
   134  		if err != nil {
   135  			result = nil
   136  			break
   137  		}
   138  		if result == nil {
   139  			result = make(map[string]string)
   140  		}
   141  		result[name] = value
   142  	}
   143  	return result
   144  }
   145  
   146  /*CanKeyMatchStructField
   147  key是否匹配field
   148  */
   149  func CanKeyMatchStructField(key string, field *reflect.StructField) bool {
   150  	if key == field.Name {
   151  		return true
   152  	}
   153  	tagMap := ParseStructTag(string(field.Tag))
   154  	if tagMap != nil {
   155  		for _, v := range tagMap {
   156  			if v == key {
   157  				return true
   158  			}
   159  		}
   160  	}
   161  	return false
   162  }