mardi 2 février 2021

get value from pointer using reflection [duplicate]

Unfortunately I don't know how to put this properly to words but I'm hoping I don't make many mistakes.

What I'm trying is to achieve is a wrapper for gin framework which will serialize JSON, get data from other part of request like path etc and populate all that on a struct before passing into a handler.

My idea is to have struct's tag tell me if they need some fields from cookies, headers, path, query parameter, etc.

So far, I'm able to use reflection and properly convert JSON, and then populate extra fields based on my factory of populators, but the last step where I'm supposed to call that handler which accepts my struct, I'm having issues.

I'm using reflect.ValueOf(Handler).Call([]reflect.Value{reflect.ValueOf(request)}) to make the call, but unfortunately I'm getting an error like this following:

reflect: Call using *main.User as type main.User

I'll also post stripped go code which you can run to check what I'm doing:

package main

import (
    "encoding/json"
    "github.com/gin-gonic/gin"
    "reflect"
)

type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
    // Authorization string `in:"header" name:"Authorization"` removed everything related to this functionality for simplicity
}

type UserResponse struct {
    Name string `json:"name"`
}

type Wrapper struct {}

func (t Wrapper) Handler(handler interface{}) func(context *gin.Context) {
    request := reflect.TypeOf(handler).In(0)
    return func(context *gin.Context) {
        req := reflect.New(request).Interface()
        json.NewDecoder(context.Request.Body).Decode(&req)
        response := reflect.ValueOf(handler).Call([]reflect.Value{reflect.ValueOf(req)})
        context.JSON(200, response[0])
    }
}

func main() {
    router := gin.Default()
    t := Wrapper{}
    router.POST("/", t.Handler(func(user User) UserResponse {
        return UserResponse{
            Name: user.Name,
        }
    }))
    router.Run()
}

To test it, you can simply make a post request:

curl --location --request POST 'localhost:8080' \
--header 'Authorization: test' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "Nishchal",
    "email": "gautam.nishchal@opn.ooo"
}'

This should result on the panic error I mentioned.

I've tried bunch of things, like changing from req to &req, tried bunch of other stackoverflow posts, but nothing helped. I feel like I'm missing something simple.

If I'm able to somehow get the value instead of pointer, I'd be in luck.

Any help would be appreciated.

Thanks in advance.





Aucun commentaire:

Enregistrer un commentaire