解组为接口类型
Unmarshall into an interface type
我希望下面的代码打印一个结构类型 J
的对象,但是它打印了一个 map[string]interface{}
类型的地图对象。我能感觉到它为什么会这样,但是当我 运行、reflect.ValueOf(i).Kind() 时,它 returns Struct
,所以它有点给了我印象是 Unmarshal
方法应该 return 键入 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)
}
您传递给 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
,则直接将其传入。如果您需要将其分配给中间接口,请确保使用指向原始值的指针,而不是指向其接口的指针。
http://play.golang.org/p/uJDFKfSIxN
j := J{}
var i interface{} = &j
js := "{\"Text\": \"lala\"}"
json.Unmarshal([]byte(js), i)
fmt.Printf("%#v", i)
这是预期的行为:不是给 json.Unmarshal
一个指向内存中正确类型位置的指针,而是给它一个指向内存中类型为 interface{}
的位置的指针。它基本上可以在 JSON 定义的类型下存储任何内容,所以它就是这样做的。
这样看:
Unmarshal
获取存储类型为 interface{}
的数据 v
的位置
Unmarshal
检测到编码为 JSON 的地图
Unmarshal
看到目标类型是 interface{}
类型,从中创建一个 go map 并将其存储在 v
中
如果您给它一个不同于 interface{}
的类型,则该过程将如下所示:
Unmarshal
获取存储类型为 struct main.J
的数据 v
的位置
Unmarshal
检测到编码为 JSON 的地图
Unmarshal
看到目标类型是struct main.J
,开始递归拟合数据到 类型
要点是,初始赋值
var i interface{} = j
被json.Unmarshal
完全忽略了。
我希望下面的代码打印一个结构类型 J
的对象,但是它打印了一个 map[string]interface{}
类型的地图对象。我能感觉到它为什么会这样,但是当我 运行、reflect.ValueOf(i).Kind() 时,它 returns Struct
,所以它有点给了我印象是 Unmarshal
方法应该 return 键入 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)
}
您传递给 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
,则直接将其传入。如果您需要将其分配给中间接口,请确保使用指向原始值的指针,而不是指向其接口的指针。
http://play.golang.org/p/uJDFKfSIxN
j := J{}
var i interface{} = &j
js := "{\"Text\": \"lala\"}"
json.Unmarshal([]byte(js), i)
fmt.Printf("%#v", i)
这是预期的行为:不是给 json.Unmarshal
一个指向内存中正确类型位置的指针,而是给它一个指向内存中类型为 interface{}
的位置的指针。它基本上可以在 JSON 定义的类型下存储任何内容,所以它就是这样做的。
这样看:
Unmarshal
获取存储类型为interface{}
的数据 Unmarshal
检测到编码为 JSON 的地图
Unmarshal
看到目标类型是interface{}
类型,从中创建一个 go map 并将其存储在v
中
v
的位置
如果您给它一个不同于 interface{}
的类型,则该过程将如下所示:
Unmarshal
获取存储类型为struct main.J
的数据 Unmarshal
检测到编码为 JSON 的地图
Unmarshal
看到目标类型是struct main.J
,开始递归拟合数据到 类型
v
的位置
要点是,初始赋值
var i interface{} = j
被json.Unmarshal
完全忽略了。