github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/reflect.go (about)

     1  package util
     2  
     3  import (
     4  	"reflect"
     5  )
     6  
     7  // ReplaceFuncVar for replace funcVar with fn
     8  func ReplaceFuncVar(funcVarPtr interface{}, fn func(in []reflect.Value) (out []reflect.Value)) {
     9  
    10  	v, ok := funcVarPtr.(reflect.Value)
    11  	if !ok {
    12  		v = reflect.ValueOf(funcVarPtr)
    13  	}
    14  
    15  	v = reflect.Indirect(v)
    16  
    17  	if v.Kind() != reflect.Func {
    18  		panic("funcVarPtr must point to a func")
    19  	}
    20  
    21  	v.Set(reflect.MakeFunc(v.Type(), fn))
    22  }
    23  
    24  // Func2Value wraps a func with reflect.Value
    25  func Func2Value(fun interface{}) reflect.Value {
    26  	v := reflect.ValueOf(fun)
    27  	if v.Kind() != reflect.Func {
    28  		panic("fun must be a func")
    29  	}
    30  	return v
    31  }
    32  
    33  // FuncInputTypes for retrieve func input types
    34  func FuncInputTypes(fun interface{}) (result []reflect.Type) {
    35  	fv, ok := fun.(reflect.Value)
    36  	if !ok {
    37  		fv = reflect.ValueOf(fun)
    38  	}
    39  
    40  	if fv.Kind() != reflect.Func {
    41  		panic("fun must be a func")
    42  	}
    43  
    44  	tp := fv.Type()
    45  	n := tp.NumIn()
    46  	for i := 0; i < n; i++ {
    47  		result = append(result, tp.In(i))
    48  	}
    49  
    50  	return
    51  }
    52  
    53  // FuncOutputTypes for retrieve func output types
    54  func FuncOutputTypes(fun interface{}) (result []reflect.Type) {
    55  	fv, ok := fun.(reflect.Value)
    56  	if !ok {
    57  		fv = reflect.ValueOf(fun)
    58  	}
    59  
    60  	if fv.Kind() != reflect.Func {
    61  		panic("fun must be a func")
    62  	}
    63  
    64  	tp := fv.Type()
    65  	n := tp.NumOut()
    66  	for i := 0; i < n; i++ {
    67  		result = append(result, tp.Out(i))
    68  	}
    69  
    70  	return
    71  }
    72  
    73  // TypeByPointer for retrieve reflect.Type by a pointer value
    74  func TypeByPointer(tp interface{}) reflect.Type {
    75  	return reflect.TypeOf(tp).Elem()
    76  }
    77  
    78  // InstanceByType returns a instance of reflect.Type wrapped in interface{}
    79  func InstanceByType(t reflect.Type) interface{} {
    80  	return reflect.New(t).Elem().Interface()
    81  }
    82  
    83  // InstancePtrByType returns a pointer to instance
    84  func InstancePtrByType(t reflect.Type) interface{} {
    85  	return reflect.New(t).Interface()
    86  }
    87  
    88  // InstancePtrByClone creates an instance ptr by clone
    89  func InstancePtrByClone(v reflect.Value) interface{} {
    90  	cv := reflect.New(v.Type())
    91  	cv.Elem().Set(v)
    92  	return cv.Interface()
    93  }
    94  
    95  // StructFieldValues for manipulate field values
    96  func StructFieldValues(s interface{}, filter func(name string, f reflect.Value) bool) (fields map[string]reflect.Value) {
    97  	v, ok := s.(reflect.Value)
    98  	if !ok {
    99  		v = reflect.ValueOf(s)
   100  	}
   101  	v = reflect.Indirect(v)
   102  
   103  	fields = make(map[string]reflect.Value)
   104  	t := v.Type()
   105  	count := v.NumField()
   106  	for i := 0; i < count; i++ {
   107  		field := v.Field(i)
   108  		name := t.Field(i).Name
   109  		if filter == nil {
   110  			fields[name] = field
   111  		} else if filter(name, field) {
   112  			fields[name] = field
   113  		}
   114  	}
   115  
   116  	return
   117  }
   118  
   119  // StructFields for general struct field info
   120  func StructFields(s interface{}) (fields []reflect.StructField) {
   121  	v, ok := s.(reflect.Value)
   122  	if !ok {
   123  		v = reflect.ValueOf(s)
   124  	}
   125  	v = reflect.Indirect(v)
   126  
   127  	t := v.Type()
   128  	count := v.NumField()
   129  	for i := 0; i < count; i++ {
   130  		field := t.Field(i)
   131  		fields = append(fields, field)
   132  	}
   133  
   134  	return
   135  }
   136  
   137  // ScanMethods for scan methods of s
   138  func ScanMethods(s interface{}) (methods map[string]reflect.Value) {
   139  	v, ok := s.(reflect.Value)
   140  	if !ok {
   141  		v = reflect.ValueOf(s)
   142  	}
   143  
   144  	methods = make(map[string]reflect.Value)
   145  	t := v.Type()
   146  	count := v.NumMethod()
   147  	for i := 0; i < count; i++ {
   148  		methods[t.Method(i).Name] = v.Method(i)
   149  	}
   150  
   151  	return
   152  }