12

我想将 JSON 文件解析为map[string]interface{}

var migrations map[string]interface{}
json.Unmarshal(raw, &migrations)

fmt.Println(migrations["create_user"])

但是我修改了我的代码以将数据指向interface{}

var migrations interface{}
json.Unmarshal(raw, &migrations)

// compile wrong here
fmt.Println(migrations["create_user"])

我不太了解上述情况map[string]interface{}之间的区别。interface{}

4

2 回答 2

35

这两种类型之间的区别就是它看起来的样子:

  1. interface{}是“any”类型,因为所有类型都实现了没有函数的接口。

  2. map[string]interface{}是一个映射,其键是字符串,值是任何类型。

当将字节数组从 JSON 解组到内存时,最容易使用该interface{}类型,因为它可以存储任何类型的 JSON 文档(对象、数组、原语等);但是,它可能需要更多的反射来处理基础数据。map[string]interface{}当您知道 JSON 文档是一个对象时使用 a很常见,而[]interface{}当您知道文档是一个数组时使用 a 很常见。

但是,解组 JSON 的最佳方法(尤其是当您提前知道文档的结构时)是定义和使用准确描述数据的自定义结构类型。通过这种方式,您可以避免任何反射并提高代码的易读性。

于 2018-02-26T16:48:58.607 回答
13

这是因为默认情况下您需要键入 assert interface{} 来获取 map[string]interface{} 的底层值。

根据GoLang规范

对于接口类型的表达式 x 和类型 T,主表达式

x.(T)

断言 x 不是 nil 并且存储在 x 中的值是 T 类型。符号 x.(T) 称为类型断言。

函数还Unmarshal需要指向migrationinterface{} 或 map[string]interface{} 类型的指针

var migrations interface{}
json.Unmarshal(raw, &migrations)

fmt.Println(migrations.(interface{}).(map[string]interface{})["create_user"])

因为migrations不是地图。所以你不能使用它的键来获取值。Interface{} 没有键

于 2018-02-26T12:49:29.857 回答