func main() {
a := 100
va, vp := reflect.ValueOf(a), reflect.ValueOf(&a).Elem()
fmt.Println(va.CanAddr(), va.CanSet())
fmt.Println(vp.CanAddr(), vp.CanSet())
}
输出:
false false
true true
就算传入指针,一样需要通过 Elem() 获取目标对象。因为被接口存储的指针本身是不能寻址和进行设置操作的。
注意,不能对非导出字段直接进行设置操作,无论是当前包还是外包。
type User struct {
Name string
code int
}
func main() {
p := new(User)
v := reflect.ValueOf(p).Elem()
name := v.FieldByName("Name")
code := v.FieldByName("code")
fmt.Printf("name: canaddr = %v, canset = %vn", name.CanAddr(), name.CanSet())
fmt.Printf("code: canaddr = %v, canset = %vn", code.CanAddr(), code.CanSet())
if name.CanSet() {
name.SetString("Tom")
}
if code.CanAddr() {
*(*int)(unsafe.Pointer(code.UnsafeAddr())) = 100
}
fmt.Printf("%+vn", *p)
}
输出:
name: canaddr = true, canset = true
code: canaddr = true, canset = false
{Name:Tom code:100}
Value.Pointer 和 Value.Int 等方法类型,将 Value.data 存储的数据转换为指针,目标必须是指针类型。而 UnsafeAddr 返回任何 CanAddr Value.data 地址(相当于 & 取地址操作),比如 Elem() 后的 Value,以及字段成员地址。
以结构体里的指针类型字段为例,Pointer 返回该字段所保存的地址,而 UnsafeAddr 返回该字段自身的地址(结构对象地址 + 偏移量)。
可通过 Interface 方法进行类型 推荐 和 转换。
func main() {
type user struct {
Name string
Age int
}
u := user{
"q.yuhen",
60,
}
v := reflect.ValueOf(&u)
if !v.CanInterface() {
println("CanInterface: fail.")
return
}
p, ok := v.Interface().(*user)
if !ok {
println("Interface: fail.")









