Go中reflect包可获取数组长度、遍历元素并修改值,但因数组是值类型,修改原数组须传指针;Len()获取长度需先用Kind()校验类型,Index(i)取元素后需Interface()转换类型。

在 Go 中,reflect 包可用于运行时获取数组信息(如长度)、遍历元素、甚至修改值,但需注意:Go 的数组是值类型且长度固定,reflect 操作的是其副本,若要修改原数组,必须传入指针。
获取数组长度
使用 reflect.Value.Len() 可获取数组长度。该方法对数组、切片、map、channel 都有效,但对非上述类型会 panic,因此建议先用 Kind() 校验。
示例:
arr := [3]int{10, 20, 30}
v := reflect.ValueOf(arr)
if v.Kind() == reflect.Array {
fmt.Println("长度:", v.Len()) // 输出:3
}
遍历数组元素
通过 Len() 获取长度后,用 Index(i) 逐个取元素。注意:Index() 返回的是 reflect.Value,需调用 Interface() 转为实际类型才能使用。
立即学习“go语言免费学习笔记(深入)”;
常见写法:
- 只读遍历(传值):直接用
reflect.ValueOf(arr) - 可写遍历(修改原数组):必须传指针,再用
Elem()获取底层数组的可寻址 Value
示例(只读):
arr := [3]string{"a", "b", "c"}
v := reflect.ValueOf(arr)
for i := 0; i < v.Len(); i++ {
elem := v.Index(i).Interface()
fmt.Printf("索引 %d: %v\n", i, elem) // 输出 a, b, c
}
修改数组元素
要真正修改原数组,必须传入指针,并确保该 reflect.Value 是可设置的(CanSet() == true)。通常需满足两个条件:原始值本身可寻址(如变量而非字面量),且反射值由指针解引用而来。
正确做法:
- 用
reflect.ValueOf(&arr).Elem()得到可设置的数组 Value - 检查
v.CanSet(),避免 panic - 用
Index(i).Set(x)修改单个元素,x必须是同类型且可赋值的reflect.Value
示例:
arr := [2]int{1, 2}
v := reflect.ValueOf(&arr).Elem() // 注意 .Elem()
if v.CanSet() {
v.Index(0).SetInt(99)
v.Index(1).SetInt(88)
}
fmt.Println(arr) // [99 88]
注意事项与限制
数组在 Go 中长度属于类型的一部分(如 [3]int 和 [4]int 是不同类型),reflect 无法改变其长度;若需动态操作,应考虑使用切片([]T)并配合 reflect.MakeSlice 等函数。
其他要点:
- 对常量数组字面量(如
reflect.ValueOf([2]int{1,2}))得到的 Value 不可设置 - 数组传递给函数默认是复制,反射操作副本不影响原变量,除非显式传指针
- 性能敏感场景慎用反射,编译期已知长度时优先用原生语法(
len(arr),for i := range arr)










