Json 在围棋中,你如何把棋子解到正确的顺序?
看起来,如果我有一个接口{}以特定的顺序在Go中,我将它封送到一个[]字节,然后将它反封送回接口{},它应该保持原始顺序。事实并非如此。结果是,正如您在下面的程序中看到的,DeepEqual无法匹配这两个Json 在围棋中,你如何把棋子解到正确的顺序?,json,go,marshalling,unmarshalling,Json,Go,Marshalling,Unmarshalling,看起来,如果我有一个接口{}以特定的顺序在Go中,我将它封送到一个[]字节,然后将它反封送回接口{},它应该保持原始顺序。事实并非如此。结果是,正如您在下面的程序中看到的,DeepEqual无法匹配这两个 package main import ( "encoding/json" "fmt" "reflect" ) func main() { var jd interface{} j := map[string]interface{}{
package main
import (
"encoding/json"
"fmt"
"reflect"
)
func main() {
var jd interface{}
j := map[string]interface{}{
"A": map[string]interface{}{"a": 1, "b": 2, "c": 3},
"B": map[string]interface{}{"a": 1, "b": 2, "c": 3},
"C": map[string]interface{}{
"a": map[string]interface{}{"a": 1, "b": 2, "c": 3},
"b": map[string]interface{}{"a": 1, "b": 2, "c": 3},
"c": map[string]interface{}{"a": 1, "b": 2, "c": 3},
},
}
s, _ := json.Marshal(j)
_ = json.Unmarshal(s, &jd)
fmt.Println(string(s))
fmt.Println(j)
fmt.Println(jd)
if !reflect.DeepEqual(j, jd) {
fmt.Println("Fail!")
}
}
该程序的结果是随机的,但这是一个典型的结果:
{"A":{"a":1,"b":2,"c":3},"B":{"a":1,"b":2,"c":3},"C":{"a":{"a":1,"b":2,"c":3},"b":{"a":1,"b":2,"c":3},"c":{"a":1,"b":2,"c":3}}}
map[B:map[a:1 b:2 c:3] C:map[c:map[a:1 b:2 c:3] a:map[b:2 c:3 a:1] b:map[a:1 b:2 c:3]] A:map[c:3 a:1 b:2]]
map[A:map[a:1 b:2 c:3] B:map[a:1 b:2 c:3] C:map[b:map[c:3 a:1 b:2] c:map[a:1 b:2 c:3] a:map[a:1 b:2 c:3]]]
Fail!
如您所见,这些值编组为原始顺序,但解编组为随机顺序(此程序的多次运行将产生不同的结果)。结果是DeepEqual比较每次都失败(到目前为止)
这是围棋中的虫子吗?是否有人可以建议解决方案
映射上的迭代顺序没有指定,也不能保证
从一次迭代到下一次迭代都是一样的
根据设计,映射上的迭代顺序是伪随机的。映射的顺序不是它不相等的原因。(如果两次解组,将得到两个完全相等的贴图,它们的顺序仍然随机不同。) : 如果您按以下方式更改代码,它将起作用:
var num float64 = 0;
j := map[string]interface{}{
"A": map[string]interface{}{"a": num+1, "b": num+2, "c": num+3},
"B": map[string]interface{}{"a": num+1, "b": num+2, "c": num+3},
"C": map[string]interface{}{
"a": map[string]interface{}{"a": num+1, "b": num+2, "c": num+3},
"b": map[string]interface{}{"a": num+1, "b": num+2, "c": num+3},
"c": map[string]interface{}{"a": num+1, "b": num+2, "c": num+3},
},
}
然后,您可以将num的类型更改为任何其他类型,它将失败。必须强烈反对此答案。迭代器顺序不能解释差异:
reflect.DeepEqual
完全能够比较映射。从第116行开始的实现表明映射比较不受迭代顺序的影响。lossleader的回答是正确的。也就是说,这助长了一种错误的假设,即最初的提问者对reflect.DeepEqual
的行为有误解。提问者将这种不平等归因于观察到这两个值的打印方式不同。实际上,重要的是数字类型的差异reflect.DeepEqual
不关心如何打印值。我已经用您建议的更改进行了测试,它确实通过了DeepEqual,尽管显示的映射顺序不同。谢谢你的帮助。一个有趣的注意事项是,尽管显示顺序不正确,但如果封送回字符串,顺序始终会恢复。换句话说,在内部,数据必须是原始顺序。只有println显示出了问题。我必须确定一下,但真正的go是在编组时进行排序以规范化json格式:因此相当多的go结构(就类型而言)映射到特定的json表示,然后可以将其解组到特定的go结构(就类型而言)在运行时迭代期间仍然具有随机排序的映射。。强排序+松散排序和强排序+松散排序之间的有趣界面。
var num float64 = 0;
j := map[string]interface{}{
"A": map[string]interface{}{"a": num+1, "b": num+2, "c": num+3},
"B": map[string]interface{}{"a": num+1, "b": num+2, "c": num+3},
"C": map[string]interface{}{
"a": map[string]interface{}{"a": num+1, "b": num+2, "c": num+3},
"b": map[string]interface{}{"a": num+1, "b": num+2, "c": num+3},
"c": map[string]interface{}{"a": num+1, "b": num+2, "c": num+3},
},
}