我正在编写一个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

如果我try 强制转换为列表类型:

matches := response["matches"].([]string)

我惊慌失措:

panic: interface conversion: interface is []interface {}, not []string [recovered]

我想在这里写什么?

推荐答案

GO中使用映射的JSON解析使用接口everywhere.假设您有以下JSON对象:

{
    "stuff" : [
        "stuff1",
        "stuff2",
        "stuff3",
    ]
}

正如您在代码中看到的那样,Go JSON库将把外部对象解析为从键到值的映射.它将变量名作为键映射到与这些变量名对应的值.然而,由于它无法提前知道这些值are是什么,因此映射的值类型仅为interface{}.假设您知道有一个名为"stuff"的键,并且知道它的值是一个array.您可以执行以下操作:

arr := myMap["stuff"]

您知道它是一个数组类型,所以您实际上可以这样做:

arr := myMap["stuff"].([]interface{})

这里的问题是,虽然您认为它是一个数组是正确的,并且JSON库知道这一点,但是它无法知道每个元素都是string类型的,所以它无法决定数组类型实际上应该是[]string.想象一下,如果您这样做了:

{
    "stuff" : [
        "stuff1",
        "stuff2",
        3
    ]
}

"stuff"现在不能是字符串数组,因为其中一个元素不是字符串.事实上,它不可能是anything的数组——没有一种类型可以满足所有元素的类型.这就是为什么Go JSON库别无 Select ,只能将其保留为[]interface{}.幸运的是,既然你想要的只是长度,你已经完成了.你可以这样做:

arr := myMap["stuff"].([]interface{})
l := len(arr)

现在这一切都很好,但假设接下来你想看看其中一个元素.现在,您可以取出一个元素,知道它是一个字符串,然后执行以下操作:

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

NOTE

当我说"数组"时,我指的是JSON意义上的数组——这些是JSONarray.在Go中表示它们的数据 struct 被称为"切片"(Go也有数组,但它们是一个独立的东西——如果你习惯了C或Java等语言中的数组,Go切片是最接近的类似物).

Go相关问答推荐

macOS上GoLand 2023.3.4中的代码导航

租户GUID X的租户不存在self 邮箱帐户的租户(我是唯一的成员)

如何防止程序B存档/删除围棋中程序A当前打开的文件?

Date.Format正在输出非常奇怪的日期

如何从 nil 指针创建值

如何根据地址和大小打印字符串

启动套接字服务器会干扰 gRPC/http 客户端服务器通信 Golang

如何从 Go Lambda 函数返回 HTML?

我无法使用反向代理更改主机标头

创建新对象后如何返回嵌套实体?

Apache Beam 左加入 Go

如何将元素从一个切片移动到另一个切片

如何为导入的嵌入式 struct 文字提供值?

来自洪流公告的奇怪同行字段

为什么 Go 被认为是部分抢占式的?

GORM GIN 更新查询导致 500 内部服务器错误

为什么 template.ParseFiles() 没有检测到这个错误?

如何扩充 ResponseWriter 的 Header() 返回的 map

函数参数的判断顺序是什么?

为什么在 unsafe.Sizeof() 中取消引用 nil 指针不会导致panic ?