检查方法类型是否与函数类型匹配

Check if a method type matches a function type

给定以下示例,如何检查方法是否匹配函数签名?

package main

import (
    "fmt"
    "context"
    "reflect"
)

// signature to check
type Fn func(context.Context)

type testStruct struct {}

func (*testStruct) DoSomething(context.Context){}
func (*testStruct) DoSomethingElse([]byte){}


func main() {
    structType := reflect.TypeOf(&testStruct{})
    for i := 0; i < structType.NumMethod(); i++ {
        fmt.Println("======================")
        method := structType.Method(i)
        fmt.Println(method.Name)
        fmt.Println(method.Type.String())

        // compare method and Fn signature
    }
}

https://play.golang.org/p/rIDfp0E14ge

1。使用 reflect.Value.Type().ConvertibleTo

注意 reflect.ValueOf 代替了 reflect.TypeOf

package main

import (
    "context"
    "fmt"
    "reflect"
)

type Fn func(context.Context)

type testStruct struct{}

func (*testStruct) DoSomething(context.Context)           {}
func (*testStruct) DoSomethingElse([]byte)                {}
func (*testStruct) DoSomethingElse2(context.Context) error { return nil }

func main() {
    structType := reflect.ValueOf(&testStruct{})
    for i := 0; i < structType.NumMethod(); i++ {
        fmt.Println("======================")
        method := structType.Method(i)

        // compare method and Fn
        if method.Type().ConvertibleTo(reflect.TypeOf((Fn)(nil))) {
            fmt.Println("function of correct type")
        }
    }
}

https://play.golang.org/p/A9_bpURinad

2。分别检查输入和输出

package main

import (
    "context"
    "fmt"
    "reflect"
)

type Fn func(context.Context)

type testStruct struct{}

func (*testStruct) DoSomething(context.Context) {}
func (*testStruct) DoSomethingElse([]byte)      {}

func main() {
    structType := reflect.TypeOf(&testStruct{})
    rctx := reflect.TypeOf(new(context.Context)).Elem()
    for i := 0; i < structType.NumMethod(); i++ {
        fmt.Println("======================")
        method := structType.Method(i)
        fmt.Println(method.Name)
        fmt.Println(method.Type.String())

        if method.Type.NumIn() != 2 {
            fmt.Println("wrong number of inputs, expected 1")
            continue
        }

        if method.Type.In(1) != rctx {
            fmt.Println("input of wrong type, expected context.Context")
            continue
        }

        if method.Type.NumOut() != 0 {
            fmt.Println("wrong number of outputs, expected 0")
            continue
        }

        fmt.Printf("%v is a function of correct type\n", method.Name)
    }
}

https://play.golang.org/p/YDsJ9MSiumF