Can I create a new function using reflection in Go

2019-03-25 06:56发布

问题:

I have an idea to use interfaces in Go to define RPC style interfaces. So for a given service, I might create an interface like this:

type MyService interface{
  Login(username, password string) (sessionId int, err error)
  HelloWorld(sessionId int) (hi string, err error)
}

What I would like to do is use reflection to implement that interface, translating method calls into RPC calls, Marshaling the input parameters, and Unmarshaling the results back into the output of the method. I know that if I can get a []interface{} of the input parameters I can use reflection to make the service call. However I don't see any way to use reflection to dynamically create a value that would implement the interface by calling my reflection-using functions. Does anyone know of a way to do this, even using unsafe?

回答1:

You can not create a type with attached methods via reflection, as to instantiate an object of that type.

You could possibly achieve this with a lot of hackery through the unsafe package. But even then, it'd be a massive pain.

If you elaborated more on the problem you're trying to solve, the community could come up with alternatives ways of solving it.

Edit (23. July 2015): starting with Go 1.5 there's reflect.FuncOf and reflect.MakeFunc, which do exactly what you want.



回答2:

It appears that the reflect package will gain the ability to create new arbitrarily typed functions in Go 1.1: reflect.MakeFunc.

(the following added in response to @nemo)

Instead of an interface, one could create a struct type:

type MyService struct{
  Login func(username, password string) (sessionId int, err error)
  HelloWorld func(sessionId int) (hi string, err error)
}

autorpc.ImplementService(&MyService, MyServiceURL)
session, err := MyService.Login(username, password)
stringout, err := MyService.HelloWorld(session)


回答3:

I think it might be possible to achieve what you want if one could fully implement the reflect.Type interface, which you can't (unexported methods). Then it could, maybe, be possible to instantiate your custom type by using unsafe_New.

All in all it is not a good idea to do so.

The next best thing to what you want is probably to use something like gob. You can use gob as intermediate language, read the methods from your interface using reflection, write them as gob and decode the created gob code to real Go objects. But I'm not sure if that's worth it.

Most of the time you're safer by manually implementing your interface on the client side and forwarding the method calls.



回答4:

Due to the static nature of the language, there is no way to implement an interface dynamically in Go at this point in time.

I understand what you want to achieve and there are other scenarios that would also benefit of a more advanced reflection capability (e.g. a good mocking framework for unit tests)


That said, there is a way that you could workaround this problem. You could write your own tool which generates a Go source code file containing a given RPC implementation of an interface.

You would have to use the AST library, as well as others, to parse and process the source interface.

Having gone down that path (gostub tool; can use as reference), I can say it is not at all fun and easy. Still, the end result is bearable since Go provides the go:generate functionality, which at least makes rerunning the tool, once an interface has changed, a tad easier.



标签: reflection go