我在golang中开发了一些服务器。我尝试创建一些包装函数,这可以帮助我将来。
我有什么:
1)我有一些DTO结构,例如:
type Request struct {
Field1 string `json:"field1"`
Field2 string `json:"field2"`
}
type Response struct {
Field1 string `json:"field1"`
Field2 string `json:"field2"`
Field3 string `json:"field3"`
}
2)我在控制器层中有一些函数,它们(通过约定)接收1个参数(指向struct的指针)并返回1个结果(指向struct的指针),例如:
func SomeHandler(request *Request) *Response{
...do something
return &Response{"first","second","third"}
}
我需要什么:
我需要编写以参数形式接收的包装函数:
此包装函数必须:
包装器必须与任何类型的“控制器”功能一致才能正常工作 - 此功能的签名不同(不同的参数类型,不同的结果类型)
有人可以帮我实现这个包装吗?
答案 0 :(得分:1)
您正在做的事情有点奇怪,但reflect
可以提供您需要的所有信息。
func myFunction(a string, b int32) error {
return nil
}
func myWrapper(mystery interface{}) {
typ := reflect.TypeOf(mystery)
// Check typ.Kind before playing with In(i);
for i := 0; i < typ.NumIn(); i++ {
fmt.Printf("Param %d: %v\n", i, typ.In(i))
}
for i := 0; i < typ.NumOut(); i++ {
fmt.Printf("Result %d: %v\n", i, typ.Out(i))
}
}
打印:
Param 0: string
Param 1: int32
Result 0: error
答案 1 :(得分:0)
这样的事情应该有效(未经测试):
func wrapper(ctlr interface{}, w http.ResponseWriter, r *http.Request) error {
tpe := reflect.TypeOf(ctlr)
if tpe.Kind() != reflect.Func || tpe.NumIn() != 1 || tpe.NumOut() != 1 {
// TODO: handle wrong ctlr type
}
// 1. Determine type of argument of 'controller' function
argt := tpe.In(0)
// 2. Determine type of result of 'controller' function
// rest := tpe.Out(0) // commented out since it's useless
// 3. Instantiate and fill argument value from Body of *http.Request (decode from json)
arg := reflect.Zero(argt)
err := json.NewDecoder(r.Body).Decode(&arg)
if err != nil {
// TODO: handle err
}
// 4. Call controller Function with instantiated on previous step argument
resv := reflect.ValueOf(ctlr).Call([]reflect.Value{arg})[0]
// 5. Write results of previous step into http.ResponseWriter (encoded as json)
err = json.NewEncoder(w).Encode(resv.Interface())
if err != nil {
// TODO: handle err
}
return nil
}
请注意,第二步是不必要的。