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

     1  package zreflect
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  )
     7  
     8  func ForEachMethod(valof reflect.Value, fn func(index int, method reflect.Method, value reflect.Value) error) error {
     9  	numMethod := valof.NumMethod()
    10  	if numMethod == 0 {
    11  		return nil
    12  	}
    13  
    14  	tp := toRType(NewType(valof))
    15  	var err error
    16  	for i := 0; i < numMethod; i++ {
    17  		err = fn(i, tp.Method(i), valof.Method(i))
    18  		if err != nil {
    19  			return err
    20  		}
    21  	}
    22  
    23  	return nil
    24  }
    25  
    26  var (
    27  	// SkipChild Field is returned when a struct field is skipped.
    28  	SkipChild = errors.New("skip struct")
    29  )
    30  
    31  // ForEach For Each Struct field
    32  func ForEach(typ reflect.Type, fn func(parent []string, index int, tag string, field reflect.StructField) error) (err error) {
    33  	var forField func(typ reflect.Type, parent []string) error
    34  	forField = func(typ reflect.Type, parent []string) error {
    35  		for i := 0; i < typ.NumField(); i++ {
    36  			field := typ.Field(i)
    37  			fieldTag, _ := GetStructTag(field)
    38  
    39  			err = fn(parent, i, fieldTag, field)
    40  			if err == SkipChild {
    41  				continue
    42  			}
    43  
    44  			if err == nil && field.Type.Kind() == reflect.Struct {
    45  				err = forField(field.Type, append(parent, fieldTag))
    46  			}
    47  
    48  			if err != nil {
    49  				return err
    50  			}
    51  		}
    52  		return nil
    53  	}
    54  
    55  	return forField(typ, []string{})
    56  }
    57  
    58  // ForEachValue For Each Struct field and value
    59  func ForEachValue(val reflect.Value, fn func(parent []string, index int, tag string, field reflect.StructField, val reflect.Value) error) (err error) {
    60  	if !Nonzero(val) {
    61  		return errors.New("reflect.Value is zero")
    62  	}
    63  
    64  	typ := toRType(NewType(val))
    65  	var forField func(val reflect.Value, typ reflect.Type, parent []string) error
    66  	forField = func(val reflect.Value, typ reflect.Type, parent []string) error {
    67  		for i := 0; i < typ.NumField(); i++ {
    68  			field := typ.Field(i)
    69  			fieldValue := val.Field(i)
    70  			fieldTag, _ := GetStructTag(field)
    71  			if field.PkgPath != "" {
    72  				continue
    73  			}
    74  
    75  			err = fn(parent, i, fieldTag, field, fieldValue)
    76  			if err == SkipChild {
    77  				continue
    78  			}
    79  
    80  			if err == nil && field.Type.Kind() == reflect.Struct {
    81  				err = forField(fieldValue, field.Type, append(parent, fieldTag))
    82  			}
    83  
    84  			if err != nil {
    85  				return err
    86  			}
    87  		}
    88  
    89  		return nil
    90  	}
    91  
    92  	return forField(val, typ, []string{})
    93  }