B. *_*lor 4 reflection dictionary go slice
在编写通用差异和补丁算法的过程中,我遇到了反射问题。
当我尝试修补切片时,我没有问题,reflect.ValueOf(&slice).Elem().Index(0).CanSet()返回true。这使我可以对slice元素内的任何内容进行修补,无论是原始元素还是结构的切片。
但是,当我尝试使用地图reflect.ValueOf(&map).Elem().MapIndex(reflect.ValueOf("key")).CanSet()返回false时。这样可以防止我尝试对地图内容做任何事情。
切片
s := []string{"a", "b", "c"}
v := reflect.ValueOf(&s).Elem()
e := v.Index(1)
println(e.String())
println(e.CanSet())
e.Set(reflect.ValueOf("d"))
for _, v := range s {
print(v, " ")
}
output :
b
true
a d c
Run Code Online (Sandbox Code Playgroud)
地图
m := map[string]string{
"a": "1",
"b": "2",
"c": "3"}
mv := reflect.ValueOf(&m).Elem()
println(mv.MapIndex(reflect.ValueOf("a")).CanSet())
output:
false
Run Code Online (Sandbox Code Playgroud)
如何通过反射从地图中获得可修改的价值?
谢谢你的时间。
这不是reflect包装的限制。切片索引表达式是可寻址的(例如&s[0]有效),因此可以设置通过反射获得的切片元素。地图索引表达式不可寻址(例如&m["a"],无效),因此无法设置通过反射获得的键的值。查看相关的如何在Go中更新地图值
只有可寻址的值是可设置的,尝试“设置”不可寻址的值只能修改副本(而不是原始值),因此一开始就不允许这样做。引用自Value.CanSet():
CanSet报告v的值是否可以更改。值只能是可寻址的,并且不是通过使用未导出的结构字段获得的,才可以更改。
如果要使用反射更改分配给映射中的键的值,请使用以下Value.SetMapIndex()方法:
mv.SetMapIndex(reflect.ValueOf("a"), reflect.ValueOf("11"))
fmt.Println(m)
Run Code Online (Sandbox Code Playgroud)
输出将是(在Go Playground上尝试):
map[b:2 c:3 a:11]
Run Code Online (Sandbox Code Playgroud)
注意:不允许使用地图索引表达式的地址(并允许使用反射来更改值),因为地图的内部结构可能随时更改(例如,如果将新的键值添加到地图中,则实现可能必须重新构造它在内部存储键值对的方式),因此在&m["a"]最终使用它时,您将获得的可能的指针可能不存在(或指向另一个值)。为避免此类混乱和运行时恐慌,首先不允许这样做。
| 归档时间: |
|
| 查看次数: |
464 次 |
| 最近记录: |