x := 2 // value type variable?
a := reflect.ValueOf(2) // 2 int no
b := reflect.ValueOf(x) // 2 int no
c := reflect.ValueOf(&x) // &x *int no
d := c.Elem() // 2 int yes (x)
fmt.Println(a.CanAddr()) // "false"
fmt.Println(b.CanAddr()) // "false"
fmt.Println(c.CanAddr()) // "false"
fmt.Println(d.CanAddr()) // "true"
| 方法名 | 备 注 |
|---|---|
| Elem() Value |
取值指向的元素值,类似于语言层*操作。当值类型不是指针或接口时发生宕 机,空指针时返回 nil 的 Value |
| Addr() Value |
对可寻址的值返回其地址,类似于语言层&操作。当值不可寻址时发生宕机 |
| CanAddr() bool | 表示值是否可寻址 |
| CanSet() bool | 返回值能否被修改。要求值可寻址且是导出的字段 |
| Set(x Value) | 将值设置为传入的反射值对象的值 |
|---|---|
| Setlnt(x int64) | 使用 int64 设置值。当值的类型不是 int、int8、int16、 int32、int64 时会发生宕机 |
| SetUint(x uint64) | 使用 uint64 设置值。当值的类型不是 uint、uint8、uint16、uint32、uint64 时会发生宕机 |
| SetFloat(x float64) | 使用 float64 设置值。当值的类型不是 float32、float64 时会发生宕机 |
| SetBool(x bool) | 使用 bool 设置值。当值的类型不是 bod 时会发生宕机 |
| SetBytes(x []byte) | 设置字节数组 []bytes值。当值的类型不是 []byte 时会发生宕机 |
| SetString(x string) | 设置字符串值。当值的类型不是 string 时会发生宕机 |
package main
import (
"reflect"
)
func main() {
// 声明整型变量a并赋初值
var a int = 1024
// 获取变量a的反射值对象
valueOfA := reflect.ValueOf(a)
// 尝试将a修改为1(此处会发生崩溃)
valueOfA.SetInt(1)
}
程序运行崩溃,打印错误:
panic: reflect: reflect.Value.SetInt using unaddressable value
报错意思是:SetInt 正在使用一个不能被寻址的值。从 reflect.ValueOf 传入的是 a 的值,而不是 a 的地址,这个 reflect.Value 当然是不能被寻址的。将代码修改一下,重新运行:
package main
import (
"fmt"
"reflect"
)
func main() {
// 声明整型变量a并赋初值
var a int = 1024
// 获取变量a的反射值对象(a的地址)
valueOfA := reflect.ValueOf(&a)
// 取出a地址的元素(a的值)
valueOfA = valueOfA.Elem()
// 修改a的值为1
valueOfA.SetInt(1)
// 打印a的值
fmt.Println(valueOfA.Int())
}
代码输出如下:
1
下面是对代码的分析:&操作;Elem() 方法类似于语言层的*操作,但并不代表这些方法与语言层操作等效。
package main
import (
"reflect"
)
func main() {
type dog struct {
legCount int
}
// 获取dog实例的反射值对象
valueOfDog := reflect.ValueOf(dog{})
// 获取legCount字段的值
vLegCount := valueOfDog.FieldByName("legCount")
// 尝试设置legCount的值(这里会发生崩溃)
vLegCount.SetInt(4)
}
程序发生崩溃,报错:
panic: reflect: reflect.Value.SetInt using value obtained using unexported field
报错的意思是:SetInt() 使用的值来自于一个未导出的字段。
type dog struct {
LegCount int
}
然后根据字段名获取字段的值时,将字符串的字段首字母大写,修改后的代码如下:
vLegCount := valueOfDog.FieldByName("LegCount")
再次运行程序,发现仍然报错:
panic: reflect: reflect.Value.SetInt using unaddressable value
这个错误表示第 13 行构造的 valueOfDog 这个结构体实例不能被寻址,因此其字段也不能被修改。修改代码,取结构体的指针,再通过 reflect.Value 的 Elem() 方法取到值的反射值对象。修改后的完整代码如下:
package main
import (
"reflect"
"fmt"
)
func main() {
type dog struct {
LegCount int
}
// 获取dog实例地址的反射值对象
valueOfDog := reflect.ValueOf(&dog{})
// 取出dog实例地址的元素
valueOfDog = valueOfDog.Elem()
// 获取legCount字段的值
vLegCount := valueOfDog.FieldByName("LegCount")
// 尝试设置legCount的值(这里会发生崩溃)
vLegCount.SetInt(4)
fmt.Println(vLegCount.Int())
}
代码输出如下:
4
代码说明如下:
版权说明:Copyright © 广州松河信息科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州松河信息科技有限公司 版权所有