实现思路
- 使用
reflect.ValueOf
获取结构体的 reflect.Value
,并通过 Elem
方法获取可设置的 reflect.Value
(如果是指针类型)。
- 遍历结构体的字段,对于每个字段,根据其类型进行不同处理:
- 如果是数组或切片,递归处理每个元素。
- 如果是 map,遍历 map 的键值对并递归处理值。
- 如果是结构体,递归处理结构体的所有字段。
- 保存原始值,修改字段值。
- 处理完所有字段后,再通过反射将修改前保存的值还原回去。
核心代码
package main
import (
"fmt"
"reflect"
)
// 定义嵌套结构体
type Inner struct {
Name string
}
type Outer struct {
ID int
Inner Inner
Data []int
Map map[string]int
}
func modifyAndRestore(obj interface{}) {
valueOf := reflect.ValueOf(obj)
if valueOf.Kind() == reflect.Ptr {
valueOf = valueOf.Elem()
}
if valueOf.Kind() != reflect.Struct {
panic("obj must be a struct or a pointer to a struct")
}
// 保存原始值
originalValues := make([]reflect.Value, valueOf.NumField())
for i := 0; i < valueOf.NumField(); i++ {
originalValues[i] = valueOf.Field(i).Clone()
}
// 修改值
for i := 0; i < valueOf.NumField(); i++ {
modifyField(valueOf.Field(i))
}
// 还原值
for i := 0; i < valueOf.NumField(); i++ {
valueOf.Field(i).Set(originalValues[i])
}
}
func modifyField(field reflect.Value) {
switch field.Kind() {
case reflect.Struct:
for i := 0; i < field.NumField(); i++ {
modifyField(field.Field(i))
}
case reflect.Array, reflect.Slice:
for i := 0; i < field.Len(); i++ {
modifyField(field.Index(i))
}
case reflect.Map:
for _, key := range field.MapKeys() {
modifyField(field.MapIndex(key))
}
default:
// 这里可以进行具体的修改操作,比如将所有字符串字段改为 "modified"
if field.Kind() == reflect.String {
field.SetString("modified")
}
}
}
func main() {
o := Outer{
ID: 1,
Inner: Inner{
Name: "original",
},
Data: []int{1, 2, 3},
Map: map[string]int{"key": 1},
}
modifyAndRestore(&o)
fmt.Printf("Restored object: %+v\n", o)
}