英文:
Writing more concise code in go
问题
我正在编写一个包,其中包含从XML-RPC服务器读取数据并将其存储在Go结构体数组中的函数。这里是一个片段,只涉及两种结构体:http://play.golang.org/p/a1dVA0UCzS。对于每种类型的结构体,我都有一个单独的“转换”函数。总共有超过20个这样的函数,它们只是彼此的简单副本,只是结构体名称不同。
有没有一种优雅的解决方案,而不是愚蠢地复制/粘贴相同的代码?
英文:
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?
答案1
得分: 2
你可以使用反射来实现这个功能。请参考pkg/reflect
文档。
对于你的情况,reflect.MakeFunc
是一个有趣的函数。你可以使用反射来创建函数,然后发送消息并知道它们将接收的类型。以下是一个示例用法:
var getFooRequest func() []Foo // 请求的原型。
buildRequest("FooStore.GetFoo", &getFooRequest) // 构建请求函数。
result := getFooRequest() // 实际发送请求。
这是一个可工作的示例(play):
func makeRequestFunc(req string, fptr interface{}) {
baseRequestFunc := func(params []reflect.Value) []reflect.Value {
log.Println("发送", 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
是你调用store.client.Call
的地方,你可以使用任何你喜欢的字符串。从这个基本函数中,你可以创建一个可通过reflect.MakeFunc
调用的新函数,并将结果存储在传递的函数指针中。
由于fooRequest
具有明确的签名,不需要进行值解包。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论