如何在Go中实例化未知类型的值?

I develop some server in golang. I try to create some wrapper-function, which can helps me in future.

What I have:

1) I had some DTO structs, for example:

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) I had some functions, in controller layer, which (by conventions) receives 1 argument (pointer to struct) and returns 1 result (pointer to struct), for example:

func SomeHandler(request *Request) *Response{
    ...do something
    return &Response{"first","second","third"}
}

What I need:

I need to write wrapper function which receives as argument:

  1. pointer to 'controller' function
  2. http.ResponseWriter
  3. *http.Request

This wrapper function must:

  1. Determine type of argument of 'controller' function
  2. Determine type of result of 'controller' function
  3. Instantiate and fill argument value from Body of *http.Request (decode from json)
  4. Call controller Function with instantiated on previous step argument
  5. Write results of previous step into http.ResponseWriter (encoded as json)

Wrapper must work correct with any types of 'controller' functions - signatures of this functions is different (different argument type, different result type)

Can anybody help me with implementing of this wrapper?

What you're doing is a bit weird but reflect can provide all the info you need.

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
", i, typ.In(i))
    }
    for i := 0; i < typ.NumOut(); i++ {
        fmt.Printf("Result %d: %v
", i, typ.Out(i))
    }

}

This prints:

Param 0: string
Param 1: int32
Result 0: error

Something like this should work (untested):

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
}

Note that the second step is unnecessary.