Исходники и презентации
This commit is contained in:
56
lessons/generics_and_reflection/private_fields_1/main.go
Normal file
56
lessons/generics_and_reflection/private_fields_1/main.go
Normal file
@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type Data struct {
|
||||
age int8
|
||||
address string
|
||||
}
|
||||
|
||||
func getFieldOffset(instance interface{}, fieldName string) (uintptr, error) {
|
||||
instanceValue := reflect.ValueOf(instance)
|
||||
if instanceValue.Kind() != reflect.Ptr {
|
||||
return 0, fmt.Errorf("the first parameter must be a pointer to a struct")
|
||||
}
|
||||
|
||||
instanceType := instanceValue.Type().Elem()
|
||||
field, found := instanceType.FieldByName(fieldName)
|
||||
if !found {
|
||||
return 0, fmt.Errorf("field '%s' not found in the struct", fieldName)
|
||||
}
|
||||
|
||||
return field.Offset, nil
|
||||
}
|
||||
|
||||
func AssignPrivateField[T any, V any](src *T, field string, value V) error {
|
||||
offset, err := getFieldOffset(src, field)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get offset: %w", err)
|
||||
}
|
||||
|
||||
fieldPtr := (*V)(unsafe.Add(unsafe.Pointer(src), offset))
|
||||
*fieldPtr = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReadPrivateField[T any, V any](src *T, field string) (V, error) {
|
||||
var output V
|
||||
|
||||
offset, err := getFieldOffset(src, field)
|
||||
if err != nil {
|
||||
return output, fmt.Errorf("get offset: %w", err)
|
||||
}
|
||||
|
||||
output = *(*V)(unsafe.Add(unsafe.Pointer(src), offset))
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
data := &Data{}
|
||||
_ = AssignPrivateField(data, "address", "Moscow")
|
||||
fmt.Println(data)
|
||||
}
|
||||
Reference in New Issue
Block a user