利用反射修改结构体私有字段
package main
import (
"fmt"
"reflect"
"unsafe"
)
type Example struct {
privateField string
}
//kind 大类型:指针,结构体 type 小类型:string,int
//非导出字段=私有字段=小写字母开头 , 导出字段=公有字段=大写字母开头
func modifyPrivateField(obj interface{}, fieldName string, newValue interface{}) (err error) {
defer func() {
//recover 捕获异常
if r := recover(); r != nil {
err = fmt.Errorf("panic occurred: %v", r)
}
}()
val := reflect.ValueOf(obj)
//fmt.Println(val.Kind()) ptr
//fmt.Println(val.Elem().Kind()) struct
if val.Kind() != reflect.Ptr || val.Elem().Kind() != reflect.Struct {
return fmt.Errorf("obj must be a pointer to struct")
}
field := val.Elem().FieldByName(fieldName)
//IsValid 字段是否有效
if !field.IsValid() {
return fmt.Errorf("field %s not found", fieldName)
}
if !field.CanSet() {
// 使用reflect包的非导出方法绕过私有限制
//UnsafeAddr获取结构体字段的内存地址
//unsafe.Pointer 直接操作内存地址,修改值或者类型转换
//field.Type() string
//reflect.NewAt 通过指定内存地址 p 和类型 typ,直接构造该地址上的反射对象,无需通过常规的 new 或字面量创建
//println(field.Type().Name()) string
field = reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem()
}
newVal := reflect.ValueOf(newValue)
if field.Type() != newVal.Type() {
return fmt.Errorf("type mismatch: %v != %v", field.Type(), newVal.Type())
}
field.Set(newVal)
return nil
}
func main() {
example := &Example{privateField: "initial"}
fmt.Println("Before:", example.privateField)
err := modifyPrivateField(example, "privateField", "modified")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("After:", example.privateField)
}