我正在尝试使用反射从两个地图中删除相同的键。但是,从第一个映射中删除它会导致更改键值。这是WAI还是一个bug。
代码(http://play.golang.org/p/MIkFP_Zrxb):
func main() {
m1 := map[string]bool{"a": true, "b": true}
m2 := map[string]bool{"a": true, "b": true}
fmt.Println(m1)
v1 := reflect.ValueOf(m1)
k := v1.MapKeys()[0]
fmt.Println("KEY BEFORE", k)
v1.SetMapIndex(k, reflect.Value{}) // COMMENT THIS OUT
fmt.Println("m1:", m1)
fmt.Println("KEY AFTER", k)
v2 := reflect.ValueOf(m2)
v2.SetMapIndex(k, reflect.Value{})
fmt.Println("KEY AFTER SECOND CALL", k)
fmt.Println("m2:", m2)
}
生成此输出:
map[a:true b:true]
KEY BEFORE a
m1: map[b:true]
KEY AFTER
KEY AFTER SECOND CALL
m2: map[a:true b:true]
请注意" a"值不会从m2中删除。注释掉指示的行会导致调用v2.SetMapIndex。
还要注意" k"的价值。调用SetMapIndex后更改。这似乎是SetMapIndex不起作用的原因。任何人都可以提供解释吗?这是一个错误吗?任何建议的解决方法?
感谢。
答案 0 :(得分:0)
我认为这是一个错误? reflect.SetMapIndex
的文档声明“如果val为零值,则SetMapIndex将从地图中删除密钥。”所以似乎正在发生的事情是关键是从反射类型下的地图中删除?值得注意的是,即使删除后,k
仍然是string
:
fmt.Println(k.Kind())
fmt.Println(k.Len())
输出:
string
0
答案 1 :(得分:0)
我提交了一个错误:https://code.google.com/p/go/issues/detail?id=7896
它固定在提示中,但尚未传播到稳定版本。
此解决方法是构造代码,以便作为密钥源的地图是从中删除的最后一个地图。 (即,在原始帖子中反转对SetMapIndex()的调用将按预期运行。
答案 2 :(得分:-1)
对SetMapIndex
的调用将在删除操作期间触及完整的键/值对。
从概念的角度来看,这对我有意义。从地图中删除键/值对时,不应保证密钥保持不变。
不确定您要实现的目标,但可能会使用k2 := v2.MapKeys()[0]
从地图v2
中删除。但正如所建议的那样,不要对这样的事情使用反射。使用例如更好内置删除功能。
您还可以查看来源以了解原始详细信息:
http://golang.org/src/pkg/reflect/value.go