2014-10-06 27 views
0

我正在尝试编写一个函数,它接受任意类型的某种类型的内容或可以生成并返回任意类型的函数。要做到这一点,我必须能够通常测试一个参数是否是一个函数,而不用测试它是否是返回类型X的函数。我该怎么做?可能看起来像下面这样:如何在接口变量上做类型断言来测试它是否是函数?

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

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

这样做是失败的。也许类型断言不是在这里使用的东西。或者,我可能只是不知道语法。将不胜感激任何建议。目前我所知道的只是把它分成两个函数,一个接受要存储的数据,另一个预计会得到一个函数,但在两种情况下,这似乎都是过度的,目标是简单地获得一个值并将其传递给函数的其余部分。

对此的任何想法?

+1

类型的断言似乎并不婆可行(静态与运行时类型检查:http://stackoverflow.com/a/21496374/6309)。这给你留下了反思。 – VonC 2014-10-06 18:30:59

回答

5

类型断言适用于特定类型。如果您知道函数的类型始终的类型为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

+0

我没有想到'func()interface {}'上的类型断言。 +1 – VonC 2014-10-06 18:44:04

+0

鉴于固有的低效率,尽可能地避免反思。我确实尝试了类型断言方法,但是我收到了一个错误:http://play.golang.org/p/FjlOLsu4sP – meesterguyperson 2014-10-06 18:55:09

+0

啊,是的,那样做。从前面的实验中飘浮在那里的杂散func()引起麻烦。谢谢。 – meesterguyperson 2014-10-06 19:03:35

相关问题