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

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

问题描述

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

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
  }

习惯上,来自 OOP 语言的背景,这种模式对我来说试图说"是 B 必须实现接口 A.但我现在明白Go 是不同的".因此,与我最初预期的编译时检查不同,无论是否使用

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 { .... }

现在.正如上面的问题所指出的(释义):当您只想实现接口的/part/时,在结构中使用嵌入式接口非常有用".

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".

大概是因为这个嵌入发生的事情就像在所有其他情况下一样 - 类型 B 的值将具有类型 A 的匿名接口值作为字段.就我个人而言,虽然我发现正交性令人欣慰,但我也发现反射包会让我以这种方式直接从 B 的类型获取 A 的方法,如果不存在接收器 B 的方法,则不会出错/零.但是 - 这个问题不是关于背后的想法 - 它是关于在 b := B{}:

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
",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?

也就是说 - 是否有关于 bMeth 值的一些信息,我可以使用它来查看反射返回的返回 Method 和 func 值中不存在真实"实现?更准确地说,是匿名接口值的函数表中函数的指针为零",还是从没有实现的带有反射的接口中提取的方法究竟发生了什么?

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?

将整个事情包装在一个 goroutine 中并尝试在 defer/panic 下运行函数不是答案——不仅是因为 panic/defer 的开销,而且因为函数通常可能,如果它确实存在,有我现在不想要的副作用...

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?

Go 游戏场中的上述示例

推荐答案

你不需要在我脑海中反思

You needn't reflection to my mind

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

会输出你

func(main.B) string

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

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天全站免登陆