map[string]interface{} 和 interface{} 的区别

Difference between map[string]interface{} and interface{}

我想将 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{} 之间的区别。

因为默认需要输入assert interface{}来获取map[string]interface{}的底层值

根据GoLang规范

For an expression x of interface type and a type T, the primary expression

x.(T)

asserts that x is not nil and that the value stored in x is of type T. The notation x.(T) is called a type assertion.

另外 Unmarshal 函数需要指向 migration 类型接口{}或映射[string]接口{}

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

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

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

这两种类型之间的区别就像看起来一样:

  1. interface{} 是 "any" 类型,因为 所有 类型实现没有功能的接口。

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

从 JSON 解组字节数组到内存时,使用 interface{} 类型最简单,因为它可以存储任何类型的 JSON 文档(对象、数组、基元、 ETC。);然而,它可能需要更多的反射来处理底层数据。当您知道 JSON 文档是一个对象时,使用 map[string]interface{} 很常见,而当您知道文档是一个数组时,使用 []interface{} 很常见。

但是,解组的最佳方法 JSON - 特别是当您提前知道文档的结构时 - 是定义和使用准确描述数据的自定义结构类型。这样您就可以避免任何反射并提高代码的可读性。