如何在interface {}变量上进行类型断言以测试其是否为函数?

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?

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
}

playground