dqroc48068 2015-05-01 14:20
浏览 25
已采纳

通过嵌入在struct中的接口进行反射-如何检测“真实”函数?

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

  • 写回答

4条回答 默认 最新

  • dragon7713 2015-05-01 18:36
    关注

    You needn't reflection to my mind

    method_in_table := B.Foo
    fmt.Printf("%T 
    ", 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()}
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 问题重发,R语言:代码运行过程中出现如下警告,请求如何解决!
  • ¥15 神经网络模型一直不能上GPU
  • ¥15 苍穹外卖拦截器token为null
  • ¥15 pyqt怎么把滑块和输入框相互绑定,求解决!
  • ¥20 wpf datagrid单元闪烁效果失灵
  • ¥15 券商软件上市公司信息获取问题
  • ¥100 ensp启动设备蓝屏,代码clock_watchdog_timeout
  • ¥15 Android studio AVD启动不了
  • ¥15 陆空双模式无人机怎么做
  • ¥15 想咨询点问题,与算法转换,负荷预测,数字孪生有关