Go映射和接口{}
我对go中以下声明的合法性有疑问。为什么我不能直接转换这两种类型Go映射和接口{},go,types,type-conversion,Go,Types,Type Conversion,我对go中以下声明的合法性有疑问。为什么我不能直接转换这两种类型 package main import ( "fmt" ) type xtype interface{} type ytype map[string]map[string]bool func main() { myvar := map[string]xtype{ "x": map[string]interface{}{ "
package main
import (
"fmt"
)
type xtype interface{}
type ytype map[string]map[string]bool
func main() {
myvar := map[string]xtype{
"x": map[string]interface{}{
"foo": map[string]interface{}{
"bar": true,
},
},
}
x := myvar["x"] // x is of type 'xtype'
fmt.Println(x) // Prints map[foo:map[bar:true]]
y := x.(ytype) // Panic
fmt.Println(y) //
}
这段代码可以编译,但在运行时,会出现恐慌
panic:interface conversion:main.xtype是map[string]接口{},而不是main.ytype
有人能解释为什么这是恐慌吗?显然,在这种情况下,它们属于同一类型。有可能在Go中进行这种直接转换吗
编辑
虽然这是一个人为的例子,但在现实世界中确实会出现。例如,Cloud Firestore的(Firebase的一部分)Go库以
map[string]接口{}
的形式从数据库返回地图,不管它们有多深。因此,如果您试图隐式转换嵌套接口,那么直接将其转换为目标类型将非常方便x
属于interface{}
类型,根据您的结构,它包含一个map[string]interface{}
。然后,该映射中包含的接口各自持有一个map[string]接口{}
,而这些最终接口各自持有一个bool。不能在一次快照中将接口{map[string]接口{}{map[string]接口{}{bool}
转换为map[string]map[string]bool
,因为这需要同时打开外部接口(由x
持有的接口),映射中的每个内部接口,然后是每个内部映射中保存布尔值的每个接口。由于每个映射级别中可能有多个键,所以这是一个O(n)操作(实际上,更接近O(n*m)),并且接口转换是专门设计的,所以您不能进行单行O(n)转换
如果您专门展开每一层,并且一次只尝试展开一个接口,那么它可以正常工作。另外,您可以使用fmt.Printf(“%#v”)
打印有关所讨论变量的显式类型信息
请参阅。由于接口{}不是map[string]bool.Duplicate,因此它们显然不是同一类型。
package main
import (
"fmt"
)
type xtype interface{}
type ytype map[string]map[string]bool
func main() {
myvar := map[string]xtype{
"x": map[string]interface{}{
"foo": map[string]interface{}{
"bar": true,
},
},
}
x := myvar["x"] // x is of type 'xtype'
fmt.Printf("%#v\n", x) // map[string]interface {}{"foo":map[string]interface {}{"bar":true}}
mid := x.(map[string]interface{})
fmt.Printf("%#v\n", mid) // map[string]interface {}{"foo":map[string]interface {}{"bar":true}}
y := make(map[string]map[string]bool)
for k, v := range mid {
m := make(map[string]bool)
for j, u := range v.(map[string]interface{}) {
m[j] = u.(bool)
}
y[k] = m
}
fmt.Printf("%#v\n", y) // map[string]map[string]bool{"foo":map[string]bool{"bar":true}}
}