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  }