go反射需传地址才能修改 切片 / 数组元素:v := reflect.ValueOf(&slice).Elem() 使 v.CanSet()为 true;仅 reflect.ValueOf(slice)不可修改,但均可读取元素。

Go 语言的反射(reflect 包)可以让你在运行时检查和操作变量的类型与值,包括数组和切片。但要注意:** 反射不能直接修改不可寻址的值,切片本身是 引用类型,但其底层数组元素是否可修改,取决于原始变量是否可寻址 **。
获取切片 / 数组的反射值
使用 reflect.ValueOf() 获取值 对象。若要后续修改,必须传入地址(如 &slice),否则得到的是不可寻址的副本:
- 错误写法:
v := reflect.ValueOf(mySlice)→v.CanSet()返回false,无法修改元素 - 正确写法:
v := reflect.ValueOf(&mySlice).Elem()→ 得到可寻址的切片值
对数组同理:v := reflect.ValueOf(&myArray).Elem() 才能修改元素。
动态读取元素
无论是否可寻址,只要值有效,就能读取:
立即学习“go 语言免费学习笔记(深入)”;
- 用
v.Index(i)获取第i个元素的reflect.Value - 调用
.Interface()转为 interface{},再类型断言获取具体值
示例:
slice := []int{10, 20, 30} v := reflect.ValueOf(slice) if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {for i := 0; i < v.len(); i++ { elem := v.Index(i).Interface() fmt.Printf(" 索引 %d: %v (类型: %s)n", i, elem, v.Index(i).Kind()) } }
动态修改元素(需可寻址)
只有通过 指针 获取的 reflect.Value 才支持修改:
- 确保
v.CanAddr() && v.CanSet()为true - 用
v.Index(i).Set(x)修改第i个元素,其中x是同类型的reflect.Value - 常用构造方式:
reflect.ValueOf(value)或reflect.ValueOf(&value).Elem()
示例(修改切片第 1 个元素为 99):
slice := []string{"a", "b", "c"} v := reflect.ValueOf(&slice).Elem() // 可寻址切片 if v.CanSet() {newVal := reflect.ValueOf("99") v.Index(1).Set(newVal) // 修改索引 1 的元素 } fmt.Println(slice) // ["a", "99", "c"]
注意事项与常见坑
反射操作切片 / 数组时容易出错,务必注意: