我希望下面的代码能够打印struct J
类型的对象,但是它会打印一个类型为map[string]interface{}
的地图对象。我可以理解为什么它会像那样,但是当我运行时,反射.ValueOf(i).Kind(),它返回Struct
,所以它有点让我觉得Unmarshal
方法应该返回类型J
代替地图。谁能开导我?
type J struct {
Text string
}
func main() {
j := J{}
var i interface{} = j
js := "{\"Text\": \"lala\"}"
json.Unmarshal([]byte(js), &i)
fmt.Printf("%#v", i)
}
答案 0 :(得分:3)
您传入Unmarshal
的类型不是*J
,而是传递给*interface{}
。
当json
包反映它收到的指针的类型时,它会看到interface{}
,因此它会使用默认类型的包进行解组,这是
bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null
几乎没有理由使用指向接口的指针。如果您发现自己使用指向界面的指针,并且您不知道完全为什么,那么它可能是一个错误。如果要解组为J
,请直接传入。{1}}。如果需要将其分配给中间接口,请确保使用指向原始值的指针,而不是指向其接口的指针。
http://play.golang.org/p/uJDFKfSIxN
j := J{}
var i interface{} = &j
js := "{\"Text\": \"lala\"}"
json.Unmarshal([]byte(js), i)
fmt.Printf("%#v", i)
答案 1 :(得分:2)
这是预期的行为:不是给json.Unmarshal
指向内存中正确类型的位置的指针,而是给它一个指向内存中类型为interface{}
的位置的指针。它本质上可以在JSON定义的类型下存储任何内容,因此它就是这样。
这样看:
Unmarshal
可以存储类型v
interface{}
Unmarshal
检测到编码为JSON Unmarshal
发现目标类型属于interface{}
类型,从中创建了一个go map并将其存储在v
如果你给它的类型不同于interface{}
,那么这个过程会是这样的:
Unmarshal
可以存储类型v
struct main.J
Unmarshal
检测到编码为JSON Unmarshal
看到目标类型为struct main.J
并开始递归地将数据拟合到类型重点是,初始分配
var i interface{} = j
完全被json.Unmarshal
忽略。