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.
Presumably, this is because what is happening with this embed is just like in every other case - an value of type B would have an anonymous interface value of type A. This question is about how that instance 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? 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 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 assertion check? Or is there an easier way? Am I thinking about this incorrectly?
Above example in a Go playground
Aucun commentaire:
Enregistrer un commentaire