前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go panic: interface conversion 接口转“父类”失败

Go panic: interface conversion 接口转“父类”失败

原创
作者头像
IT工作者
发布2022-07-22 15:35:51
6190
发布2022-07-22 15:35:51
举报
文章被收录于专栏:程序技术知识

普通的 interface 转 struct 很简单:接口对象后面加上 .(StructType) 即可.

但是复杂一点的,如接口IA的对象a是组合了Stuct A(实现了接口IA)的的Struct AA或者Struct AAA时,想通过接口转“父类”,就麻烦了, 如下:

代码语言:go
复制
package main
 
import (
    "fmt"
    //"reflect"
)
 
 
type IA interface {
    Fun()
}
 
type A struct {
 
}
 
func (slf *A) AFun(){
    fmt.Println("fun in A")
}
 
func(slf *A) Fun(){
    fmt.Println("xxx")
}
 
 
type AA struct {
    A
}
 
type AAA struct {
    A
}
 
type IFun interface {
    AFun()
}
 
func main() {
    var a AA
    var b AAA
 
    var amap = map[int]IA{}
    amap[1] = &a
    amap[2] = &b
 
    for _, a :=range amap{
        //a.Fun()
        a.(*A).AFun()
    }
}

编译能通过,但是运行时会报错:

panic: interface conversion: main.IA is *main.AA, not *main.A

如果要用amap里的接口对象调用Struct A的方法 AFun,有什么办法呢?

方法一:

这个最容易想到,就是将AFun添加到IA里。 但是如果不让修改IA呢?

方法二:

就得用到反射了:

代码语言:javascript
复制
av := reflect.ValueOf(a)
av.MethodByName("AFun").Call([]reflect.Value{})

但是反射效率不高

方法三:

代码语言:go
复制
type IFun interface {
    AFun()
}
 
for{
    a.(IFun).AFun()
}

将AFun添加到其他的接口类型,从而做到既不破坏IA,也不会用到反射。

总结

熟悉interface的话就会知道 interface是由一个方法地址列表和对应数据地址组成的,那么接口转原数据类型,很容易,也很好理解 但是接口转原数据类型中的组合(c++父类)时,编译能通过,估计就是通过反射查找它的组合关系判定合法了,但是运行时,却panic了,这个也好解释:因为运行时进行这种类型转换开销过大,得不偿失。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档