I want to test a given function in runtime, to verify that it matches a certain signature. It's sufficient that this signature complies with some interface, not a specific implementation.
I can't seem to find the right pattern to do such validation. In runtime, the function's type is using the implementation.
How can I compare the function's signature to the interface?
package main
import "fmt"
type myinteface interface{
DoSomething(int) string
}
type myfunc func(myinteface)
type impl struct {}
func (im *impl) DoSomething(int) string{
return "fsdfsd"
}
func do(i interface{}) {
switch v := i.(type) {
case func(myinteface):
fmt.Print("doesn't stop here")
case func(impl):
fmt.Print("this does work")
default:
fmt.Printf("I don't know about type %T!\n", v)
}
}
func test(im impl) {}
func main() {
do(test)
}
see it live in playground
You may check arguments type manually using reflect package. Here's an example for myinteface. I check whether first parameter Implements desired interface. For brevity I suppose function has only one obligatory argument. For production it's better to check number of arguments (commented out string with NumIn()) and all their types in a cycle.
func do(i interface{}) {
val := reflect.ValueOf(i)
typ := val.Type()
// numIn := typ.NumIn()
arg0 := typ.In(0)
modelType := reflect.TypeOf((*myinteface)(nil)).Elem()
if arg0.Implements(modelType) {
fmt.Println("OK")
} else {
fmt.Println("not OK")
}
}
Also, please pay attention to a receiver type: value or pointer. For example, here only test2 function argument implements myinteface, but test doesn't because of the pointer receiver on the struct impl.
func test(im impl) {}
func test2(im *impl) {}
func main() {
do(test)
do(test2)
}
Demo: https://play.golang.org/p/ZDZKZIh2lW
If you change struct definition to value receiver then both function's arguments implement it:
type impl struct{}
func (im impl) DoSomething(int) string {
return "fsdfsd"
}
https://play.golang.org/p/xvasgBs-_a
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With