英文:
How do I do a type assertion on an interface{} variable to test if it is a function?
问题
我正在尝试编写一个函数,它可以接受任意类型的内容或者可以生成并返回任意类型的函数作为参数。为了实现这个目标,我需要能够通用地测试一个参数是否为函数,而不是测试它是否是返回类型为X的函数。我该如何做到这一点?可能看起来像下面的代码:
func Blah(arbitrary interface{}) {
var value interface{}
if function, ok := arbitrary.(func() interface{}); ok {
value = function()
} else {
value = arbitrary
}
...
}
这段代码目前无法正常工作。也许类型断言不适合在这里使用,或者我只是不知道正确的语法。如果有任何建议,我将不胜感激。目前我唯一知道的做法是将其拆分为两个函数,一个函数接受要存储的数据,另一个函数期望得到一个函数作为参数,但是当两种情况下的目标都只是获取一个值并将其传递给函数的其余部分时,这种做法似乎有些过度设计。
对此有什么想法吗?
英文:
I am attempting to write a function that accepts either some type of content of arbitrary type or a function that can generate and return an arbitrary type. To do this, I have to be able to generally test if an argument is a function without testing for whether it is a function of return type X. How do I do this? Might look something like the following:
func Blah(arbitrary interface{}) {
var value interface{}
if function, ok := arbitrary.(func interface{}); ok {
value = function()
} else {
value = arbitrary
}
...
}
This fails as is. Maybe a type assertion isn't the thing to use here. Or maybe I just don't know the syntax. Would appreciate any suggestions. Only thing I know to do at present is to divide this up into two functions, one that accepts data to be stored as is, and another that expects to get a function, but that seems overkill when in both cases the goal is simply to get a value and pass it on to the rest of the function.
Any ideas on this?
答案1
得分: 5
类型断言适用于特定类型。如果你知道函数的类型始终为func() interface{}
,那么可以使用以下代码:
if f, ok := arbitrary.(func() interface{}); ok {
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
}
英文:
Type assertions work on specific types. If you know that the type of the function always has type func() interface{}
, then you can use:
if f, ok := arbitrary.(func() interface{}) {
value = f()
} else {
value = arbitrary
}
Note that the type func() interface{}
is a function with return type interface{}
, not a function with an arbitrary return type.
It's easy to wrap an arbitrary function to a func() interface{}
:
func hello() string { return "hello" }
wrapped := func() interface{} { return hello() }
If you cannot arrange for the function to have return type interface{}
, then you need to use reflection to test and call the function:
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
}
<kbd>playground</kbd>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论