用嵌入在结构中的接口去反射 - 如何检测“真实”功能? [英] Go reflection with interface embedded in struct - how to detect "real" functions?

查看:93
本文介绍了用嵌入在结构中的接口去反射 - 如何检测“真实”功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在的情况与在此线程中询问的情况相同:嵌入式匿名接口的结构的含义?

  type A接口{
Foo )string
}

type B struct {
A
bar string
}

在OOP语言中,从习惯上来说,它看起来像这种模式是试图说给我的是B必须实现接口A.但是我得到现在Go是不同的。因此,不用编译时检查我首先期望的,这是很高兴编译有或没有

  func(B )Foo()字符串{....} 

存在。正如上面的问题所指出的(转述):在结构中使用嵌入式接口非常适合当您只需实现/部分接口。假设这是因为这种嵌入发生的事情就像其他情况一样 - 类型B的值将具有类型A的匿名接口值,如同<! - SIPO - >一个领域。就个人而言,当我发现正交性令人欣慰时,我也发现令人困惑的是,反射包会让我以这种方式直接从B的类型获得A的方法,而如果没有接收器B的方法存在,则不会出现错误/零。但是 - 这个问题不是关于背后的想法 - 它是关于如何在 b:= B {} 之后初始化接口值:

  func main(){
bType:= reflect.TypeOf(B {})
bMeth,has:= bType.MethodByName Foo)
如果有{
fmt.Printf(HAS IT:%s\\\
,bMeth.Type.Kind())
res:= bMeth.Func.Call ([] reflect.Value {reflect.ValueOf(B {})})
val:= res [0] .Interface()
fmt.Println(val)
} else {
fmt.Println(DOESNT拥有IT)
}
}



<当它运行时,它引起恐慌

 有它:func 
panic:运行时错误:无效内存地址或零指针解引用

... 或不 - 取决于编译器/运行时是否能够找到上述方法。所以:在我触发它之前,我怎么能检测到这种情况?

也就是说,有什么关于我可以用来看的bMeth值反射返回的Method和func值中没有真实实现?更准确地说,就像是指向匿名接口值的函数表中的函数的指针,它的值为零,或者在没有实现的情况下从具有反射的接口提取的方法发生了什么?

在goroutine中包装整个事情并试图在延迟/恐慌下运行该功能不是答案 - 不仅因为恐慌/推迟的代价,而且因为一般情况下,函数可能,如果存在,有副作用,我现在不想要......



我想要类似于反映编译器类型检查的运行时实现的东西?还是有更简单的方法?我在想这个不对吗?



上面的例子在游乐场里

解决方案

您无需反思我的想法

  method_in_table:= B.Foo 
fmt.Printf(%T \\\
,method_in_table)

会输出给你

  func(main.B )字符串

接口类型A在预先声明的nil上初始化,没有动态类型

  var a A 
如果a == nil {
fmt.Printf(It's nil)
}
a.Foo()

会给你同样的错误。所以实际的检查可以是

 如果bA!= nil {b.Foo()} 


The situation I have now is the same as was asked about in this thread: Meaning of a struct with embedded anonymous interface?

  type A interface {
     Foo() string
  }

  type B struct {
     A
     bar string
  }

Idiomatically, coming from a backround in OOP languages, what it looks like this pattern is "trying to say" to me is that B must implement interface A. But I get by now that "Go is different". So, rather than the compile-time check I expected at first, this is happy to compile with or without a

  func (B) Foo() string { .... }

present. As the above question points out (paraphrased): "using embedded interfaces in structs is great for when you only want to implement /part/ of an interface".

Presumably, this is because what is happening with this embed is just like in every other case - a value of type B would have an anonymous interface value of type A, as a field. Personally while I find that orthogonality comforting, I also find it confusing that the reflection package would then let me get methods of A directly from B's type this way, and not error/nil if no method with receiver B is present. But - this question isn't about the thinking behind that - it is about how that interface value is initialized after b := B{}:

 func main() {
    bType := reflect.TypeOf(B{})
    bMeth, has := bType.MethodByName("Foo")
    if has {
      fmt.Printf("HAS IT: %s\n",bMeth.Type.Kind())
      res := bMeth.Func.Call([]reflect.Value{reflect.ValueOf(B{})})
      val := res[0].Interface()
      fmt.Println(val)
  } else {
      fmt.Println("DOESNT HAS IT")
  }
}

When this is run, it causes a horrible panic

 HAS IT: func
 panic: runtime error: invalid memory address or nil pointer dereference

... or doesn't - depending on if the compiler/runtime was able to find the above method. So: How can I detect that situation before I trigger it?

That is - is there something about the bMeth value I can use to see that there is no "real" implementation present in the reflection-returned returned Method and func values? Is that more precisely something like "is the pointer to the function in the function table of the anonymous interface value in zero", or what exactly is going on with methods you pull from an interface with reflection where there is no implementation?

Wrapping the whole thing in a goroutine and attempting to run the function under defer/panic isn't the answer - not only because of the expense of the panic/defer but because the function in general might, if it does exist, have side effects I don't want right now...

Do I want something like a run-time implementation that mirrors the compiler's type check? Or is there an easier way? Am I thinking about this incorrectly?

Above example in a Go playground

解决方案

You needn't reflection to my mind

method_in_table := B.Foo
fmt.Printf("%T \n", method_in_table)

will output you

func(main.B) string

Interface type A initialized at predeclared nil which has no dynamic type

var a A
if a==nil{
    fmt.Printf("It's nil")
}
a.Foo()

will give you same error. So practical check can be just

if b.A != nil { b.Foo()}

这篇关于用嵌入在结构中的接口去反射 - 如何检测“真实”功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆