简体   繁体   中英

interface{} to function type conversion

I'm a Go newcomer and I've been battling with this problem almost all day today.

Considering I have these:

type HandlerType func()
var object interface{}
var typedObject HandlerType

I can assign a function to the typedObject variable like this:

typedHandler = func() {
    fmt.Println("in a handler!\n")
}

But what I need to do is to pass that handler function as an interface{} variable and then convert it somehow to HandlerType which I could call later

I've tried this but it throws an error:

typedHandler = object.(HandlerType)

results in:

interface conversion: interface is func(), not main.HandlerType

Basically I need to register functions with different signatures without additional type conversion before registering. So instead of doing this:

registerHandler(HandlerTypeString(func() string { ... }))
registerHandler(HandlerTypeVoid(func() { ... }))

I want to register handlers like this:

registerHandler(func() string { ... })
registerHandler(func() { ... })

.. and I don't want to involve reflection at the time of a handler call later

Is it possible?

Edit : I've created a playground: http://play.golang.org/p/UlwqkHjt_P

So as I understand there is no way to pass some arbitrary function as interface{} and then somehow convert it to HandlerType or some other predefined function type so I would be able to call it without using reflection?

Edit2 : I've came up with this solution: http://play.golang.org/p/4gUxsgmiPf

There shouldn't be any performance penalties during runtime with this code. But can somebody think out another way of implementing this functionality without interface{} ?

You can't, it's a different type, you could just use object.(func()) , object.(func() string) , etc.

func main() {
    type HandlerType func()
    var object interface{} = func() {
        fmt.Println("eureka!")
    }
    if f, ok := object.(func()); ok {
        HandlerType(f)()
    }
}

There is a number of small misconceptions in your question:

  1. Type assertion isn't used to cast types. All it do is checking that a variable is of the given type and returning the variable as this underlying type. This operation return a error in your case, which is normal given that func() isn't the type HandlerFunc .

  2. You don't need to do anything to pass a variable as parameter in a function accepting interface{} . Every type implicitly implement the empty interface.

  3. A func() isn't a HandlerType , even if HandlerType is defined by type HandlerType func() . The definition has nothing to do with that.

What you want to do isn't possible. I'm not an expert with reflection, but I don't think that reflection could solve your problem either.

That said, your registering method should define a interface that all registered objects should implement, and use this interface as parameter type. Look at the database/sql package Register method for an example.

您现在可以使用reflect.MakeFunc执行此操作。有关于如何执行此操作的示例

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM