github.com/wfusion/gofusion@v1.1.14/common/utils/inspect/field.go (about) 1 // Inspired by github.com/chenzhuoyu/go-inspect 2 3 package inspect 4 5 import ( 6 "errors" 7 "reflect" 8 "unsafe" 9 ) 10 11 type Field struct { 12 t *rtype 13 p unsafe.Pointer 14 } 15 16 // Get returns the value of the referenced field, even if it's private. 17 func (f Field) Get() reflect.Value { 18 if f.t == nil { 19 panic(errors.New("inspect: invalid field")) 20 } 21 return reflect.ValueOf(f.read().pack()) 22 } 23 24 // Set updates the value of the referenced field, even if it's private. 25 func (f Field) Set(v reflect.Value) { 26 if f.t == nil { 27 panic(errors.New("inspect: invalid field")) 28 } 29 30 v = v.Convert(packType(f.t)) 31 typedmemmove(f.t, f.p, f.addr(v)) 32 } 33 34 func (f Field) read() eface { 35 if ifaceIndir(f.t) { 36 return eface{_type: f.t, data: f.p} 37 } else { 38 return eface{_type: f.t, data: *(*unsafe.Pointer)(f.p)} 39 } 40 } 41 42 func (f Field) addr(v reflect.Value) unsafe.Pointer { 43 if ifaceIndir(f.t) { 44 return (*eface)(unsafe.Pointer(&v)).data 45 } else { 46 return unsafe.Pointer(&((*eface)(unsafe.Pointer(&v)).data)) 47 } 48 } 49 50 func newField(v reflect.Value, fv reflect.StructField) Field { 51 return Field{ 52 t: unpackType(fv.Type), 53 p: unsafe.Pointer(uintptr((*eface)(unsafe.Pointer(&v)).data) + fv.Offset), 54 } 55 } 56 57 func derefType(t reflect.Type) reflect.Type { 58 for t.Kind() == reflect.Ptr { 59 t = t.Elem() 60 } 61 return t 62 } 63 64 func derefValue(t reflect.Value) reflect.Value { 65 for t.Kind() == reflect.Ptr { 66 t = t.Elem() 67 } 68 return t 69 }