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  }