github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zreflect/reflect.go (about) 1 package zreflect 2 3 import ( 4 "errors" 5 "reflect" 6 "unsafe" 7 8 "github.com/sohaha/zlsgo/zstring" 9 ) 10 11 type ( 12 Type = *rtype 13 rtype struct{} 14 flag uintptr 15 Value struct { 16 typ Type 17 ptr unsafe.Pointer 18 flag 19 } 20 ) 21 22 // GetUnexportedField Get unexported field, hazardous operation, please use with caution 23 func GetUnexportedField(v reflect.Value, field string) (interface{}, error) { 24 f, b, err := getField(v, field) 25 if err != nil { 26 return nil, err 27 } 28 29 if b { 30 return f.Interface(), nil 31 } 32 33 return reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Elem().Interface(), nil 34 } 35 36 // SetUnexportedField Set unexported field, hazardous operation, please use with caution 37 func SetUnexportedField(v reflect.Value, field string, value interface{}) error { 38 f, b, err := getField(v, field) 39 if err != nil { 40 return err 41 } 42 43 nv := reflect.ValueOf(value) 44 kind := f.Kind() 45 if kind != reflect.Interface && kind != nv.Kind() { 46 return errors.New("value type not match") 47 } 48 49 if b { 50 if !f.CanSet() { 51 return errors.New("field can not set") 52 } 53 f.Set(nv) 54 return nil 55 } 56 57 reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())). 58 Elem(). 59 Set(nv) 60 61 return nil 62 } 63 64 func getField(v reflect.Value, field string) (reflect.Value, bool, error) { 65 ve := reflect.Indirect(v) 66 if ve.Kind() != reflect.Struct { 67 return reflect.Value{}, false, errors.New("value must be struct") 68 } 69 70 f := ve.FieldByName(field) 71 if !f.IsValid() { 72 return reflect.Value{}, false, errors.New("field not exists") 73 } 74 75 if zstring.IsUcfirst(field) { 76 return f, true, nil 77 } 78 79 if v.Kind() != reflect.Ptr { 80 return reflect.Value{}, false, errors.New("value must be ptr") 81 } 82 return f, false, nil 83 }