我对以下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{}{
"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)转换:main.xtype 是 map[string]interface {},不是 main.ytype
有人可以解释为什么这是 panic 吗?显然,在这种情况下它们属于同一类型。是否可以在 Go 中进行这种直接转换?
编辑
虽然这是一个人为的例子,但这确实出现在现实世界中。例如,Cloud Firestore 的(Firebase 的一部分)Go 库以 map[string]interface{}
的形式从数据库返回 map ,无论 map 有多深。所以直接转换成目标类型真的很方便
最佳答案
您正在尝试隐式转换嵌套接口(interface),但这行不通。 x
类型为 interface{}
,并根据您的结构持有 map[string]interface{}
.该映射中包含的接口(interface)每个都包含一个 map[string]interface{}
。 ,而那些最终的接口(interface)每个都有一个 bool 值。您无法转换 interface{map[string]interface{}{map[string]interface{}{bool}}
到 map[string]map[string]bool
在一次拍摄中,因为这需要展开外部接口(interface)(由 x
持有的接口(interface))、映射中的每个内部接口(interface),然后是每个内部映射中包含 bool 值的每个接口(interface)。由于在每一级映射中可以有多个键,这是一个 O(n) 操作(实际上,更接近于 O(n*m)),并且接口(interface)转换是专门设计的,因此你不能单行 O(n) 转换。
如果你专门解包每一层,并且一次只尝试解包一个接口(interface),它工作得很好。在旁注中,您可以使用 fmt.Printf("%#v", <var>)
打印有关变量的显式类型信息。
https://play.golang.org/p/Ng9CE0O34G
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}}
}
关于Go map 和界面{},我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46954314/