写点什么

理解 reflect elem 和 value 的一段测试代码

用户头像
werben
关注
发布于: 2021 年 03 月 31 日

问题一:为什么 mapValue.CanSet()是 false,却可以调用 SetMapIndex

fmt.Printf("mapValue CanSet:%t\n", mapValue.CanSet())    // mapValue CanSet:falsemapValue.SetMapIndex(reflect.ValueOf("height"), reflect.ValueOf(60))
复制代码


map 和 slice 本身就是指针,当 reflect.ValueOf(m)而不是 reflect.ValueOf(&m),map 指针本身是不能修改改,也就是你不能修改 map 指向的内存地址,mapValue.CanSet()返回 false,但是内存地址里面的数据却是可以修改的 mapValue.SetMapIndex(reflect.ValueOf("height"), reflect.ValueOf(60)。这个对 C 语言指针有了解的肯定能很好理解。如下面的 c 语言代码,p 是 const 指针本身不能修改,不能再指向 b 了,但是却可以改变 a 的数值。

#include <stdio.h>
int main(){ int a = 12; int b = 22; int* const p = &a; //会报错:assignment of read-only variable 'p' //因为p指针是const的,已经是p指向a,就不能让p再指向其他地方了 //p = &b; //不报错,因为不能修改p指针,但是可以修改p指向的内存数据,比如这里的a *p = 98; //输出98 printf("%d \n", a); return 0;}
复制代码

问题二:为什么为什么修改 m 也相当于修改了 om?

这个问题跟问题一是差不多的,如果还是没理解就先去搞懂 c 语言的指针。

map 和 slice 本身就是指针,如果修改 &map 实际上是修改了 map 指针指向的内存,

mapPtrValue.Elem().Set(reflect.ValueOf(om))

实际上是使 m 和 om 都指向了同一块内存,也就是 om 原先指向的那个内存,所以当修改 m 的时候,实际修改的是 m 指向的内存里的数据,所以 om 里面的数据也改变了。

同理可以看[]int 是一样的。


package main
import ( "fmt" "reflect")
type Blog struct { ID int Name string `gorm:"embedded;embeddedPrefix:author_"` Upvotes int32}
func main() { var i int intValue := reflect.ValueOf(i) fmt.Printf("intValue value:%v\n", intValue) // intValue value:0 fmt.Printf("intValue type:%v\n", intValue.Type()) // intValue type:int fmt.Printf("intValue kind:%v\n", intValue.Type().Kind()) // intValue kind:int reflect.ValueOf(intValue) fmt.Printf("intValue CanSet:%t\n\n", intValue.CanSet()) // intValue CanSet:false
intPtrValue := reflect.ValueOf(&i) fmt.Printf("intPtrValue value:%v\n", intPtrValue) // intPtrValue value:0xc0000120a0 fmt.Printf("intPtrValue type:%v\n", intPtrValue.Type()) // intPtrValue type:*int fmt.Printf("intPtrValue kind:%v\n", intPtrValue.Type().Kind()) // intPtrValue kind:ptr fmt.Printf("intPtrValue CanSet:%t\n", intPtrValue.CanSet()) // intPtrValue CanSet:false fmt.Printf("intPtrValue Elem CanSet:%t\n", intPtrValue.Elem().CanSet()) // intPtrValue Elem CanSet:true fmt.Printf("intPtrValue Indirect CanSet:%t\n", reflect.Indirect(intPtrValue).CanSet()) // intPtrValue Indirect CanSet:true
intPtrValue.Elem().SetInt(123) fmt.Printf("intPtrValue Elem SetInt:%v\n", i) // intPtrValue Elem SetInt:123 reflect.Indirect(intPtrValue).SetInt(245) fmt.Printf("intPtrValue Indirect SetInt:%v\n\n", i) // intPtrValue Indirect SetInt:245
var str string strValue := reflect.ValueOf(str) fmt.Printf("strVal value:%v\n", strValue) // strVal value: fmt.Printf("strVal type:%v\n", strValue.Type()) // strVal type:string fmt.Printf("strVal kind:%v\n", strValue.Type().Kind()) // strVal kind:string fmt.Printf("strValue CanSet:%t\n", strValue.CanSet()) // strValue CanSet:false
strPtrValue := reflect.ValueOf(&str) fmt.Printf("strPtrValue value:%v\n", strPtrValue) // strPtrValue value:0xc0000341f0 fmt.Printf("strPtrValue type:%v\n", strPtrValue.Type()) // strPtrValue type:*string fmt.Printf("strPtrValue kind:%v\n", strPtrValue.Type().Kind()) // strPtrValue kind:ptr fmt.Printf("strPtrValue CanSet:%t\n", strPtrValue.CanSet()) // strPtrValue CanSet:false fmt.Printf("strPtrValue Elem CanSet:%t\n", strPtrValue.Elem().CanSet()) // strPtrValue Elem CanSet:true fmt.Printf("strPtrValue Indirect CanSet:%t\n", reflect.Indirect(strPtrValue).CanSet()) // strPtrValue Indirect CanSet:true
strPtrValue.Elem().SetString("abc") fmt.Printf("strPtrValue Elem SetString:%v\n", str) // strPtrValue Elem SetString:abc reflect.Indirect(strPtrValue).SetString("efg") fmt.Printf("strPtrValue Indirect SetString:%v\n\n", str) // strPtrValue Indirect SetString:efg
var blog Blog structValue := reflect.ValueOf(blog) fmt.Printf("structValue value:%v\n", structValue) // structValue value:{0 0} fmt.Printf("structValue type:%v\n", structValue.Type()) // structValue type:main.Blog fmt.Printf("structValue kind:%v\n", structValue.Type().Kind()) // structValue kind:struct fmt.Printf("structValue CanSet:%t\n", structValue.CanSet()) // structValue CanSet:false
structPtrValue := reflect.ValueOf(&blog) fmt.Printf("structPtrValue value:%v\n", structPtrValue) // structPtrValue value:&{0 0} fmt.Printf("structPtrValue type:%v\n", structPtrValue.Type()) // structPtrValue type:*main.Blog fmt.Printf("structPtrValue kind:%v\n", structPtrValue.Type().Kind()) // structPtrValue kind:ptr fmt.Printf("structPtrValue CanSet:%t\n", structPtrValue.CanSet()) // structPtrValue CanSet:false fmt.Printf("structPtrValue Elem CanSet:%t\n", structPtrValue.Elem().CanSet()) // structPtrValue Elem CanSet:true
bbb := Blog{ Name: "sdga", } structPtrValue.Elem().Set(reflect.ValueOf(bbb)) fmt.Printf("structPtrValue Set:%+v\n\n", blog) // structPtrValue Set:{ID:0 Name:sdga Upvotes:0}
m := map[string]interface{}{ "class": "class1", } fmt.Printf("m addr:%p\n", &m) mapValue := reflect.ValueOf(m)
fmt.Printf("mapValue value:%v\n", mapValue) // mapValue value:map[class:class1] fmt.Printf("mapValue type:%v\n", mapValue.Type()) // mapValue type:map[string]interface {} fmt.Printf("mapValue kind:%v\n", mapValue.Type().Kind()) // mapValue kind:map fmt.Printf("mapValue CanSet:%t\n", mapValue.CanSet()) // mapValue CanSet:false mapValue.SetMapIndex(reflect.ValueOf("height"), reflect.ValueOf(60))
mapPtrValue := reflect.ValueOf(&m) fmt.Printf("mapPtrValue value:%+v\n", mapPtrValue) // mapPtrValue value:&map[class:class1 height:60] fmt.Printf("mapPtrValue type:%v\n", mapPtrValue.Type()) // mapPtrValue type:*map[string]interface {} fmt.Printf("mapPtrValue kind:%v\n", mapPtrValue.Type().Kind()) // mapPtrValue kind:ptr fmt.Printf("mapPtrValue CanSet:%t\n", mapPtrValue.CanSet()) // mapPtrValue CanSet:false fmt.Printf("mapPtrValue Elem CanSet:%t\n", mapPtrValue.Elem().CanSet()) // mapPtrValue Elem CanSet:true
om := map[string]interface{}{ "name": "werben", "age": 16, }
mapPtrValue.Elem().SetMapIndex(reflect.ValueOf("class"), reflect.ValueOf("1")) fmt.Printf("om addr:%p\n", &om) mapPtrValue.Elem().Set(reflect.ValueOf(om)) mapPtrValue.Elem().SetMapIndex(reflect.ValueOf("addr"), reflect.ValueOf("sz")) fmt.Printf("mapPtrValue Set:%+v\n", m) // mapPtrValue Set:map[addr:sz age:16 name:werben] fmt.Printf("mapPtrValue om:%+v\n\n", om) // mapPtrValue om:map[addr:sz age:16 name:werben] fmt.Printf("m addr:%p, %p\n", &m, m) // m addr:0xc000086000, 0xc0000880f0 fmt.Printf("om addr:%p, %p\n", &om, om) // om addr:0xc000086008, 0xc0000880f0 m["avatar"] = "aaaaaaaa" om["sex"] = "girl" fmt.Printf("mapPtrValue Set:%+v\n", m) // mapPtrValue Set:map[addr:sz age:16 avatar:aaaaaaaa name:werben sex:girl] fmt.Printf("mapPtrValue om:%+v\n\n", om) // mapPtrValue om:map[addr:sz age:16 avatar:aaaaaaaa name:werben sex:girl]
arr := []int{1, 2, 3, 4, 5} arrValue := reflect.ValueOf(arr) fmt.Printf("arrValue value:%v\n", arrValue) // arrValue value:[1 2 3 4 5] fmt.Printf("arrValue type:%v\n", arrValue.Type()) // arrValue type:[]int fmt.Printf("arrValue kind:%v\n", arrValue.Type().Kind()) // arrValue kind:slice fmt.Printf("arrValue CanSet:%t\n", arrValue.CanSet()) // arrValue CanSet:false arrValue.Index(1).SetInt(123)
arrPtrValue := reflect.ValueOf(&arr) fmt.Printf("arrPtrValue value:%+v\n", arrPtrValue) // arrPtrValue value:&[1 123 3 4 5] fmt.Printf("arrPtrValue type:%v\n", arrPtrValue.Type()) // arrPtrValue type:*[]int fmt.Printf("arrPtrValue kind:%v\n", arrPtrValue.Type().Kind()) // arrPtrValue kind:ptr fmt.Printf("arrPtrValue CanSet:%t\n", arrPtrValue.CanSet()) // arrPtrValue CanSet:false fmt.Printf("arrPtrValue Elem CanSet:%t\n", arrPtrValue.Elem().CanSet()) // arrPtrValue Elem CanSet:true
orr := []int{6, 7, 8, 9, 10}
arrPtrValue.Elem().Index(1).SetInt(555) fmt.Printf("arr addr:%p, %p\n", &arr, arr) // arr addr:0xc000086140, 0xc0000920c0 arrPtrValue.Elem().Set(reflect.ValueOf(orr)) arrPtrValue.Elem().Index(1).SetInt(666) fmt.Printf("arrPtrValue Set:%+v\n", arr) // arrPtrValue Set:[6 666 8 9 10] fmt.Printf("arrPtrValue om:%+v\n", orr) // arrPtrValue om:[6 666 8 9 10] fmt.Printf("arr addr:%p, %p\n", &arr, arr) // arr addr:0xc00008e140, 0xc00008c210 fmt.Printf("orr addr:%p, %p\n\n", &orr, orr) // orr addr:0xc00008e1e0, 0xc00008c210}
复制代码


发布于: 2021 年 03 月 31 日阅读数: 13
用户头像

werben

关注

还未添加个人签名 2018.01.08 加入

还未添加个人简介

评论

发布
暂无评论
理解reflect elem和value的一段测试代码