Go 如何在接口上调用len()?

Go 如何在接口上调用len()?,go,Go,我正在编写一个JSON列表为空的测试 {"matches": []} var matches := response["matches"] if len(matches) != 0 { t.Errorf("Non-empty match list!") } 对象具有类型map[string]interface{},我想测试列表是否为空 {"matches": []} var matches := response["matches"] if len(matches) != 0 {

我正在编写一个JSON列表为空的测试

{"matches": []}
var matches := response["matches"]
if len(matches) != 0 {
    t.Errorf("Non-empty match list!")
}
对象具有类型
map[string]interface{}
,我想测试列表是否为空

{"matches": []}
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: interface conversion: interface is []interface {}, not []string [recovered]

我想在这里写什么?

在Go中使用映射进行JSON解析在任何地方都使用接口。假设您拥有以下JSON对象:

{
    "stuff" : [
        "stuff1",
        "stuff2",
        "stuff3",
    ]
}
正如您在代码中看到的,GoJSON库将外部对象解析为从键到值的映射。它将变量名作为键映射到对应于这些变量名的值。但是,由于它无法提前知道这些值是什么,因此映射的值类型只是
interface{}
。假设你知道有一个键叫做
“stuff”
,你知道它的值是一个数组。你可以做:

arr := myMap["stuff"]
您知道它是一种数组类型,因此实际上可以执行以下操作:

arr := myMap["stuff"].([]interface{})
这里的问题是,虽然您认为它是一个数组是正确的,而且JSON库知道这一点,但它无法知道每个元素的类型都是
string
,因此它无法确定数组类型实际上应该是
[]string
。想象一下,如果你这样做了:

{
    "stuff" : [
        "stuff1",
        "stuff2",
        3
    ]
}
“stuff”
现在不能是字符串数组,因为其中一个元素不是字符串。事实上,它不可能是任何东西的数组——没有一种类型可以满足所有元素的类型。因此,Go JSON库别无选择,只能将其保留为
[]接口{}
。幸运的是,由于您只需要长度,因此您已经完成了。您只需执行以下操作:

arr := myMap["stuff"].([]interface{})
l := len(arr)
现在,这一切都很好,但让我们假设,在接下来的过程中,您希望实际查看其中一个元素。现在,您可以取出一个元素,知道它是一个字符串,然后执行以下操作:

arr := myMap["stuff"].([]interface{})
iv := arr[0] // interface value
sv := iv.(string) // string value
注意


当我说“数组”时,我指的是JSON意义上的数组——这些是JSON数组。在Go中表示它们的数据结构称为“切片”(Go也有数组,但它们是一个单独的东西-如果您习惯于C或Java等语言中的数组,Go切片是最接近的类似物)。

在处理JSON时,我喜欢为Map和slice添加类型声明,然后 我可以根据需要添加方法来帮助转换:

package main
import "encoding/json"
type Map map[string]interface{}
type Slice []interface{}

func (m Map) A(s string) Slice {
   return m[s].([]interface{})
}

func main() {
   y := []byte(`{"matches": []}`)
   response := Map{}
   json.Unmarshal(y, &response)
   matches := response.A("matches")
   n := len(matches)
   println(n == 0)
}

如果可以避免,请不要使用
接口{}
。这不是当时必要的音乐。e、 例如,如果您需要的话,将其解析为`map[string][]string。或者一个结构请原谅我吹毛求疵,但是
[]接口{}
不是一个数组(用Go术语来说),它是一个切片。我知道-我指的是JSON意义上的数组。