github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zutil/reflect.go (about)

     1  package zutil
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  	"strconv"
     7  
     8  	"github.com/sohaha/zlsgo/zreflect"
     9  	"github.com/sohaha/zlsgo/ztype"
    10  )
    11  
    12  func SetValue(vTypeOf reflect.Kind, vValueOf reflect.Value, value interface{}) (err error) {
    13  	typeErr := errors.New(vTypeOf.String() + " type assignment is not supported")
    14  	vString := ""
    15  	v, ok := value.(string)
    16  	if ok {
    17  		vString = v
    18  	} else {
    19  		vString = ztype.ToString(value)
    20  	}
    21  	switch vTypeOf {
    22  	case reflect.String:
    23  		vValueOf.SetString(vString)
    24  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    25  		var v int64
    26  		v, err = strconv.ParseInt(vString, 10, 64)
    27  		if err != nil {
    28  			err = errors.New("must be an integer")
    29  		} else if vValueOf.OverflowInt(v) {
    30  			err = typeErr
    31  		}
    32  		vValueOf.SetInt(v)
    33  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
    34  		var v uint64
    35  		v, err = strconv.ParseUint(vString, 10, 64)
    36  		if err != nil {
    37  			err = errors.New("must be an unsigned integer")
    38  		} else if vValueOf.OverflowUint(v) {
    39  			err = typeErr
    40  		}
    41  		vValueOf.SetUint(v)
    42  	case reflect.Float32, reflect.Float64:
    43  		var v float64
    44  		v, err = strconv.ParseFloat(vString, 64)
    45  		if err != nil {
    46  			err = errors.New("must be decimal")
    47  		} else if vValueOf.OverflowFloat(v) {
    48  			err = typeErr
    49  		}
    50  	case reflect.Bool:
    51  		var v bool
    52  		v, err = strconv.ParseBool(vString)
    53  		if err != nil {
    54  			err = errors.New("must be boolean")
    55  		}
    56  		vValueOf.SetBool(v)
    57  	case reflect.Slice:
    58  		if value != nil {
    59  			vValueOf.Set(zreflect.ValueOf(value))
    60  		} else {
    61  			err = errors.New("must be slice")
    62  		}
    63  	case reflect.Struct:
    64  		err = setStruct(vValueOf, value)
    65  	default:
    66  		err = typeErr
    67  	}
    68  
    69  	return err
    70  }
    71  
    72  // setStruct todo unfinished
    73  func setStruct(v reflect.Value, value interface{}) (err error) {
    74  	valueTypeof := reflect.TypeOf(value)
    75  	kind := valueTypeof.Kind()
    76  	if kind != reflect.Map {
    77  		err = errors.New("must be map[]")
    78  		return
    79  	}
    80  
    81  	if values, ok := value.(map[string]string); ok {
    82  		err = ReflectForNumField(v, func(fieldName, fieldTag string, kind reflect.Kind,
    83  			field reflect.Value) error {
    84  			if v, ok := values[fieldTag]; ok {
    85  				return SetValue(kind, field, v)
    86  			}
    87  			return nil
    88  		})
    89  	} else {
    90  		err = errors.New("not supported")
    91  	}
    92  
    93  	return
    94  }
    95  
    96  func ReflectStructField(v reflect.Type, fn func(
    97  	numField int, fieldTag string, field reflect.StructField) error, tag ...string) error {
    98  	var err error
    99  	tagKey := "z"
   100  	if len(tag) > 0 {
   101  		tagKey = tag[0]
   102  	}
   103  	if v.Kind() == reflect.Ptr {
   104  		v = v.Elem()
   105  	}
   106  	for i := 0; i < v.NumField(); i++ {
   107  		field := v.Field(i)
   108  		fieldTag := ""
   109  		if tagKey != "" {
   110  			fieldTag = field.Tag.Get(tagKey)
   111  		}
   112  		if fieldTag == "-" {
   113  			continue
   114  		}
   115  		fieldName := field.Name
   116  		if fieldTag == "" {
   117  			fieldTag = fieldName
   118  		}
   119  		err = fn(i, fieldTag, field)
   120  		if err != nil {
   121  			return err
   122  		}
   123  	}
   124  	return nil
   125  }
   126  
   127  func ReflectForNumField(v reflect.Value, fn func(fieldName, fieldTag string,
   128  	kind reflect.Kind, field reflect.Value) error, tag ...string) error {
   129  	var err error
   130  	tagKey := zreflect.Tag
   131  	if len(tag) > 0 {
   132  		tagKey = tag[0]
   133  	}
   134  	for i := 0; i < v.NumField(); i++ {
   135  		field := v.Field(i)
   136  		tfield := v.Type().Field(i)
   137  		fieldTag := ""
   138  		if tagKey != "" {
   139  			fieldTag = tfield.Tag.Get(tagKey)
   140  		}
   141  		if fieldTag == "-" || !field.CanSet() {
   142  			continue
   143  		}
   144  		fieldName := tfield.Name
   145  		fieldType := field.Type()
   146  		kind := fieldType.Kind()
   147  		if fieldTag == "" {
   148  			fieldTag = fieldName
   149  		}
   150  		if kind == reflect.Struct { //  && tfield.Anonymous
   151  			if err = ReflectForNumField(field, fn, tag...); err != nil {
   152  				return err
   153  			}
   154  		}
   155  		if err = fn(fieldName, fieldTag, kind, field); err != nil {
   156  			return err
   157  		}
   158  	}
   159  	return err
   160  }
   161  
   162  // GetAllMethod get all methods of struct
   163  func GetAllMethod(s interface{}, fn func(numMethod int, m reflect.Method) error) error {
   164  	typ := zreflect.ValueOf(s)
   165  	if fn == nil {
   166  		return nil
   167  	}
   168  	return zreflect.ForEachMethod(typ, func(index int, method reflect.Method, value reflect.Value) error {
   169  		return fn(index, method)
   170  	})
   171  }
   172  
   173  // RunAllMethod run all methods of struct
   174  func RunAllMethod(st interface{}, args ...interface{}) (err error) {
   175  	return RunAssignMethod(st, func(methodName string) bool {
   176  		return true
   177  	}, args...)
   178  }
   179  
   180  // RunAssignMethod run assign methods of struct
   181  func RunAssignMethod(st interface{}, filter func(methodName string) bool, args ...interface{}) (err error) {
   182  	valueOf := zreflect.ValueOf(st)
   183  	err = GetAllMethod(st, func(numMethod int, m reflect.Method) error {
   184  		if !filter(m.Name) {
   185  			return nil
   186  		}
   187  		var values []reflect.Value
   188  		for _, v := range args {
   189  			values = append(values, zreflect.ValueOf(v))
   190  		}
   191  
   192  		return TryCatch(func() error {
   193  			valueOf.Method(numMethod).Call(values)
   194  			return nil
   195  		})
   196  	})
   197  
   198  	return
   199  }