1

So, I was trying to find the solution via the search and web-search. Wasn't successful. This has likely a simple solution, but probably I'm just a bit messed up.

I have prepared the following example in go playground.

// main.go

type myInterface interface {
    Function1() string
    Function2() int
}

type notMyStruct struct {
    myInterface
    // arbitrary implementation
}

func myFunc(val myInterface) {
    fmt.Printf("%T %v", val, val)

    fmt.Printf("this failes: %q", val.Function1())
    // how to safely test, 
    // whether the underlying value
    // has implemented the interface?
}

func main() {
    myFunc(&notMyStruct{})
}

It consists of an interface myInterface, an arbitrary struct notMyStruct, which has the embedded interface (but not actually implemented) and some other arbitrary fields. Now this struct is injected into myFunc, which the go compiler will accept, due to the fact that the interface is embedded. But if myFunc tries to call a Function of the interface, it panics – understandably.

Assuming, I don't know the actual struct implementation (because I'm not in control of the interface-implementing code):

How can I reliably test, whether a given underlying value has an actual implementation of the method set (Function1 and Function2) defined by the interface?

I assume, this is solvable with reflect package (performance is not an issue here). Maybe there's any other solutions thinkable? Type assertion didn't seem to work out for me...

m0r0n
  • 132
  • 2
  • 10
  • 1
    The type `myStruct` has implementations of `Function1` and `Function2` that call through methods with the same name on the `myInterface` field. The `reflect` package and type assertions will not tell you that the methods will panic. – Charlie Tumahai Apr 25 '20 at 19:16
  • @CeriseLimón thanks for your fast response. What would you suggest then? – m0r0n Apr 25 '20 at 19:20
  • 2
    It is not possible to determine if a method will panic without some knowledge about the implementation. If you know that a method forwards to a method on an interface field, then you can test the field for nil. – Charlie Tumahai Apr 25 '20 at 19:25
  • @CeriseLimón Alright, that's prior to calling the method. And inside that function `myFunc`? How to assert an existing implementation? – m0r0n Apr 25 '20 at 19:30
  • 2
    It's not your job to make sure the implementation does not panic. Someone could pass an implementation which has explicitly defined the methods but also they explicitly call `panic()`. You could not detect that and that wouldn't be "any better" implementation. – icza Apr 25 '20 at 20:29
  • @icza so form the content of linked threads, I believe `recover()` is the only option I have inside that method, if I want to guarantee smooth execution. Thanks for the hints – m0r0n Apr 26 '20 at 11:56
  • 1
    @m0r0n Use a [type assertion](https://golang.org/ref/spec#Type_assertions) in `myFunc` to assert that the interface value is a specific concrete type: `if nms, ok := val.(*notMyStruct); ok && nms.myInterface == nil { /* call will panic */ }` – Charlie Tumahai Apr 26 '20 at 14:46
  • Also note that this is possible, shared it in [this answer](https://stackoverflow.com/a/61448767/1705598). – icza Apr 26 '20 at 22:10

0 Answers0