我正在编写一个 JSON 列表为空的测试。
{"matches": []}
该对象的类型为 map[string]interface{}
,我想测试该列表是否为空。
var matches := response["matches"]
if len(matches) != 0 {
t.Errorf("Non-empty match list!")
}
但是我在编译时被告知这是无效的
invalid argument matches (type interface {}) for len
如果我尝试转换为列表类型:
matches := response["matches"].([]string)
我感到 panic :
panic: interface conversion: interface is []interface {}, not []string [recovered]
我想在这里写什么?
最佳答案
在 Go 中使用映射解析 JSON 无处不在。假设您有以下 JSON 对象:
{
"stuff" : [
"stuff1",
"stuff2",
"stuff3",
]
}
Go JSON 库会将外部对象解析为从键到值的映射,正如您在代码中看到的那样。它将变量名称作为键映射到与这些变量名称对应的值。但是,由于它无法提前知道这些值是什么,因此映射的值类型只是interface{}
。假设您知道有一个名为 "stuff"
的键,并且您知道它的值是一个数组。你可以这样做:
arr := myMap["stuff"]
你知道它是一个数组类型,所以你实际上可以这样做:
arr := myMap["stuff"].([]interface{})
这里的问题是,虽然你是对的,它是一个数组,而且 JSON 库知道这一点,但它无法知道每个元素都是 string
类型,所以没有它决定数组类型实际上应该是 []string
的方法。想象一下,如果您改为这样做:
{
"stuff" : [
"stuff1",
"stuff2",
3
]
}
"stuff"
现在不能是字符串数组,因为其中一个元素不是字符串。事实上,它不可能是任何东西的数组——没有一种类型可以满足所有元素的类型。所以这就是为什么 Go JSON 库别无选择,只能将其保留为 []interface{}
。幸运的是,因为你想要的只是长度,所以你已经完成了。你可以这样做:
arr := myMap["stuff"].([]interface{})
l := len(arr)
现在一切都很好,但假设您接下来想要真正查看其中一个元素。您现在可以取出一个元素,并知道它是一个字符串,然后执行以下操作:
arr := myMap["stuff"].([]interface{})
iv := arr[0] // interface value
sv := iv.(string) // string value
注意
当我说“数组”时,我指的是 JSON 意义上的数组——这些是 JSON 数组。在 Go 中表示它们的数据结构称为“slice ”(Go 也有数组,但它们是独立的东西——如果你习惯于 C 或 Java 等语言中的数组,Go slice 是最接近的类似物)。
关于go - 如何在接口(interface)上调用 len()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21070387/