1 回答
TA贡献1831条经验 获得超4个赞
如果将变量声明为 type interface{}
,则它就是type interface{}
。它永远不具有map[keytype]valuetype
某种价值。但是类型变量interface{}
可以保存具有其他具体类型的值。当它这样做时,它就这样做——仅此而已。它仍然是type interface{}
,但它包含其他类型的值。
接口值由两部分组成
这里的关键区别在于interface{}
变量是什么以及它包含什么。任何接口变量实际上都有两个槽:一个用于保存其中存储的类型,另一个用于保存其中存储的值。每当您(或任何人)为变量赋值时,编译器都会填充两个槽:类型(来自您使用的值的类型)和值(来自您使用的值)。1nil
如果接口变量在两个槽中 都有,则比较等于 nil ;这也是默认的零值。
因此,您的运行时测试:
valueMap, ok := myMap.(map[string]interface{})
是明智的做法:如果myMap
持有一个类型为 的值map[string]interface
,ok
则将其设置为true
并valueMap
包含该值(具有该类型)。如果myMap
持有某个其他类型的值,ok
则设置为false
并valueMap
设置为 类型的零值map[string]interface{}
。换句话说,在运行时,代码首先检查类型槽,然后将值槽复制到valueMap
并设置ok
为 true,或者设置valueMap
为nil
并设置ok
为 false。
如果且当ok
已设置为时true
,每个valueMap[k]
值都是type interface{}
。和以前一样,对于myMap
其本身,每个interface{}
变量都可以(但不必)保存 type 的值string
,并且您必须使用某种“实际类型和值是什么”运行时测试来区分它们。
当您将json.Unmarshal
解码后的 JSON 填充到 类型的变量中时interface{}
,它能够反序列化任何这些记录的 JSON 类型。然后该列表告诉您什么类型被填充到接口变量中:
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
因此,在执行json.Unmarshal完类型为 的变量之后interface{},您应该检查变量的类型槽中放入的类型。您可以使用断言和ok布尔值来完成此操作,或者如果您愿意,也可以使用类型开关对其进行解码:
var i interface
if err := json.Unmarshal(data, &i); err != nil {
panic(err)
}
switch v := i.(type) {
case string:
... code ...
case map[string]interface{}:
... code ...
... add some or all of the types listed ...
}
问题是,无论您在此处的代码中执行什么操作,您都确实已将某些json.Unmarshal内容放入interface{}, 并且interface{} 是的类型i。您必须在运行时测试接口保存的类型和值对。
您的另一个选择是手动检查 JSON 字符串并决定提供给 的变量类型json.Unmarshal。这使得您可以在后面编写更少的代码,但在 之前Unmarshal编写更多代码。
在 Go Playground 上有一个更完整的示例,使用类型开关来检查json.Unmarshal. 它故意不完整,但我认为,有足够的输入和输出案例,可以让您了解如何处理所有内容,考虑到上面关于写入类型变量的内容的json.Unmarshal引用interface{}。
1当然,如果您interface{}从其他地方分配一个interface{}:
var i1, i2 interface{}
... set i1 from some actual value ...
// more code, then:
i2 = i1
编译器只是将两个槽从 复制i1到i2。当你这样做时,两个独立插槽的事情就会变得更加清晰:
var f float64
... code that sets f to, say, 1.5 ...
i2 = f
例如,当写入float64类型槽时,将值1.5写入值槽中。编译器知道这f一点,float64因此类型设置只是意味着“在其中粘贴一个常量”。编译器不一定知道的值f,因此值设置是实际值的副本。
- 1 回答
- 0 关注
- 131 浏览
添加回答
举报