I'm writing a package with functions which read data from XML-RPC server and store it in arrays of go structs. Here is the snippet just for two kinds of structs: http://play.golang.org/p/a1dVA0UCzS. For each type of struct I have a separate "conversion" function. There are more than 20 of them in total - just plain copies of each other with just struct names replaced.
Is there an elegant solution instead of stupid copy/paste of the same code?
You can do this by using reflection. See the pkg/reflect
documentation.
For your case reflect.MakeFunc
is interesting. You can create functions using reflection which then send a message and know the types they will receive. Example usage:
var getFooRequest func() []Foo // Prototype of request.
buildRequest("FooStore.GetFoo", &getFooRequest) // Build request function.
result := getFooRequest() // Actually sending.
A working example (play):
func makeRequestFunc(req string, fptr interface{}) {
baseRequestFunc := func(params []reflect.Value) []reflect.Value {
log.Println("Sending", req)
return []reflect.Value{ reflect.ValueOf([]int{1,2,3,4}) }
}
fn := reflect.ValueOf(fptr).Elem()
reqFun := reflect.MakeFunc(fn.Type(), baseRequestFunc)
fn.Set(reqFun)
}
var fooRequest func() []int
makeRequestFunc("foo", &fooRequest)
log.Println( fooRequest() )
baseRequestFunc
in this example is the place where you would call your store.client.Call
with whatever string you like. From this base function you create a new function that is callable using reflect.MakeFunc
and store the result in the passed function pointer.
As fooRequest
has a definite signature, no value unpacking is needed.