在我看来,reflect.ValueOf(&x).Elem()
等于reflect.ValueOf(x)
,因为.Elem()
获取reflect.Value
包含的指针的实际值。代码来了,json.Marshal
的编码结果不同:
func generateRequest(input string, flag bool) interface{} {
val := Node {
Cmd: "Netware",
Name: input,
}
if flag {
return &val
} else {
return val
}
}
func main() {
request1 := generateRequest("123", true)
request2 := generateRequest("123", false)
request1Val := reflect.ValueOf(request1).Elem()
fmt.Println(request1Val, request2)
json1, err := json.Marshal(request1Val)
checkErr(err)
json2, err := json.Marshal(request2)
checkErr(err)
fmt.Println(json1, string(json1))
fmt.Println(json2, string(json2))
fmt.Println(reflect.DeepEqual(json1, json2))
}
下面是输出:
{Netware 123} {Netware 123}
[123 34 102 108 97 103 34 58 52 48 57 125] {"flag":409}
[123 34 99 109 100 34 58 34 78 101 116 119 97 114 101 34 44 34 110 97 109 101 34 58 34 49 50 51 34 125] {"cmd":"Netware","name":"123"}
false
我想知道为什么它们不同,以及如何修改我的代码以使request1
的编码结果与request2
相同。
答案 0 :(得分:2)
对不起,这完全是错的。反射和JSON编组不会一起使用。
json2, err := json.Marshal(request2)
部分是合理的:request2
是Node
(包含在interface{}
中,这里的事实并不有趣)。因此,callong json.Marshal会在Node
封送{"cmd":"Netware","name":"123"}
,这就是你所期望的结果。
现在json1, err := json.Marshal(request1Val)
:Go 静态 键入,而您的request1Val
类型为reflect.Value,这是一个完整的普通类型像string
或type myFoo struct {whatever}
一样。如果您将此类型的内容传递给json.Marshal,您将获得reflect.Value
的JSON序列化。不幸的是,这种序列化在任何方面都是完全无用的,因为它与reflect.Value中封装的值没有任何共同之处。想想reflect.Values是一个包含你的request1的不透明容器。不幸的是,它是不透明的,序列化不会神奇地揭示它隐藏的内容。
如果你想从reflect.Value转到它实际拥有的东西,可以使用Interface()
方法来“解开”容器,然后取回你在reflect.Value中包装的内容。
你的问题与反映的无关.ValueOf(& x).Elem()或reflect.Value(x)的确有(不)不同。你的问题源于将一个reflect.Value传递给json.Marshal,它将从不工作,无论reflect.Value实际上是什么。