go - 类型开关以通过接口(interface)验证功能

标签 go

我想在运行时测试一个给定的函数,以验证它是否匹配某个签名。这个签名符合一些接口(interface)就足够了,而不是特定的实现。

我似乎无法找到进行此类验证的正确模式。在运行时,函数的类型正在使用实现。

如何将函数的签名与接口(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)
}

现场观看 playground

最佳答案

您可以使用 reflect 手动检查参数类型包裹。下面是 myinteface 的示例。我检查第一个参数 Implements 是否需要所需的接口(interface)。为简洁起见,我假设函数只有一个强制性参数。对于生产,最好在一个循环中检查参数的数量(用 NumIn() 注释掉的字符串)及其所有类型。

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")
    }
}

此外,请注意接收者类型:值或指针。例如,这里只有 test2 函数参数实现了 myinteface,但是 test 没有,因为结构体 impl< 上的指针接收器.

func test(im impl) {}

func test2(im *impl) {}

func main() {
    do(test)
    do(test2)
}

演示:https://play.golang.org/p/ZDZKZIh2lW

如果您将结构定义更改为值接收者,那么两个函数的参数都会实现它:

type impl struct{}

func (im impl) DoSomething(int) string {
    return "fsdfsd"
}

https://play.golang.org/p/xvasgBs-_a

关于go - 类型开关以通过接口(interface)验证功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47521522/

相关文章:

go - 未定义 : revel. 测试套件

go - Go接口(interface)的一些例子是什么?

bash - 如何使用 bash -c 启动程序,重定向/禁用该应用程序的 GUI

go - 使用golang-ci lint错误提取公司软件包

go - 解码 json 错误,即使提供了匹配的数据结构

json - 使用 Go 访问嵌套数组和对象中的数据

go - 替换 viper map 键而不替换整个 map

go - 找不到函数 Marshal()

go - 在C函数中更改golang C.String变量的值

gob.Register() 按类型还是按每个变量?