我想将 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{}
之间的区别不太了解。
这两种类型之间的区别就是它看起来的样子:
-
interface{}
是"any"类型,因为所有类型都实现没有函数的接口。 -
map[string]interface{}
是一个映射,其键是字符串,值是任何类型的。
将字节数组从JSON解组到内存中时,最简单的方法是使用interface{}
类型,因为它可以存储任何类型的JSON文档(对象,数组,原语等);但是,它可能需要更多的反射来处理基础数据。 当您知道 JSON 文档是一个对象时,使用map[string]interface{}
很常见,当您知道文档是一个数组时[]interface{}
使用很常见。
但是,解封 JSON 的最佳方法 - 尤其是当您提前知道文档的结构时 - 是定义和使用准确描述数据的自定义结构类型。这样,您可以避免任何反射并提高代码的可读性。
这是因为默认情况下你需要键入assert interface{}来获取map[string]interface{}的基础值。
根据 GoLang 规范
对于接口类型和类型 T 的表达式 x,主 表达
x.(T)
断言 x 不是 nil,并且存储在 x 中的值是 T 类型。 表示法 x.(T) 称为类型断言。
此外Unmarshal
函数需要指向 interface{} 或 map[string]interface{} 类型的migration
的指针
var migrations interface{}
json.Unmarshal(raw, &migrations)
fmt.Println(migrations.(interface{}).(map[string]interface{})["create_user"])
由于migrations
不是地图。因此,您不能使用其密钥来获取值。接口{} 没有键