【问题标题】:How do I do a type assertion on an interface{} variable to test if it is a function?如何对 interface{} 变量进行类型断言以测试它是否是函数?
【发布时间】:2014-10-06 18:26:55
【问题描述】:

我正在尝试编写一个函数,该函数既可以接受某种任意类型的内容,也可以接受可以生成和返回任意类型的函数。为此,我必须能够通常测试参数是否是函数,而无需测试它是否是返回类型 X 的函数。我该怎么做?可能如下所示:

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

    if function, ok := arbitrary.(func interface{}); ok {
        value = function()
    } else {
        value = arbitrary
    }
    ...
}

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

对此有何想法?

【问题讨论】:

标签: callback go type-safety type-assertion


【解决方案1】:

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

if f, ok := arbitrary.(func() interface{}) {
    value = f()
} else {
    value = arbitrary
}

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

很容易将任意函数包装到func() interface{}

func hello() string { return "hello" }

wrapped := func() interface{} { return hello() }

如果你不能为函数安排返回类型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
}

playground

【讨论】:

  • 我没想到func() interface{} 上的类型断言。 +1
  • 真正尽量避免反射,因为它固有的低效率。我确实尝试了类型断言方法,但出现错误:play.golang.org/p/FjlOLsu4sP
  • 啊,是的,就可以了。以前的实验中出现的流浪 func() 漂浮在那里,造成了麻烦。谢谢。
猜你喜欢
  • 2021-12-04
  • 2017-08-06
  • 1970-01-01
  • 2020-05-27
  • 2016-07-27
  • 2022-01-25
  • 2019-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多