利用反射修改结构体私有字段

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)

}

posted on 2025-07-09 16:14  木林coder  阅读(8)  评论(0)    收藏  举报

导航