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 }