如何在接口{}变量上执行类型断言来测试它是否是函数?

mee*_*son 1 callback go type-safety type-assertion

我试图编写一个函数,接受任意类型的某种类型的内容或可以生成和返回任意类型的函数.要做到这一点,我必须能够通常测试一个参数是否是一个函数而不测试它是否是返回类型X的函数.我该怎么做?可能会看起来像下面这样:

func Blah(arbitrary interface{}) {
    var value interface{}

    if function, ok := arbitrary.(func interface{}); ok {
        value = function()
    } else {
        value = arbitrary
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

这样就失败了.也许类型断言不是在这里使用的东西.或许我只是不知道语法.将不胜感激任何建议.我目前唯一知道要做的就是把它分成两个函数,一个接受要按原样存储的数据,另一个希望得到一个函数,但是在两种情况下,目标只是得到,这似乎有点过头了.一个值并将其传递给函数的其余部分.

有什么想法吗?

Sim*_*Fox 5

类型断言适用于特定类型.如果你知道函数的类型总是有类型func() interface{},那么你可以使用:

if f, ok := arbitrary.(func() interface{}) {
    value = f()
} else {
    value = arbitrary
}
Run Code Online (Sandbox Code Playgroud)

请注意,类型func() interface{}是具有返回类型interface{}的函数,而不是具有任意返回类型的函数.

将任意函数包装到func() interface{}:

func hello() string { return "hello" }

wrapped := func() interface{} { return hello() }
Run Code Online (Sandbox Code Playgroud)

如果你不能安排函数有返回类型interface{},那么你需要使用反射测试并调用函数:

func isFunction(v interface{}) (func() interface{}, bool) {
  rv := reflect.ValueOf(v)
  if rv.Kind() == reflect.Func {
    return func() interface{} {
        result := rv.Call(nil)
        if len(result) > 0 {
            return result[0].Interface()
        }
        return nil
    }, true
  }

  return nil, false
}

---

if f, ok := isFunction(arbitrary); ok {
    value = f
} else {
    value = arbitrary
}
Run Code Online (Sandbox Code Playgroud)

playground