2017-12-16 09:16
浏览 147


Am new to the GO programming language. I am building a web server using the gin-gonic framework. I am trying to map the values from req.body onto a struct.

Using Postman I am sending a POST request with the following key/vaules under x-www-form-urlencoded

role : admin

username : adminusername

id: 1

my go code is as follows

package jwtsecuritytoken

import (

type requestBody struct {
    role      string
    username  string    
    id        string

func GenerateToken(c *gin.Context) {
    var reqBody requestBody
    err := c.Bind(reqBody)
    if err != nil {

    content := gin.H{"Hello": "World"}
    c.JSON(200, content)

I am able to read the value from c.PostForm("name") but when i try to bind it to the struct I get the following error

reflect: Elem of invalid type
C:/Go/src/runtime/panic.go:491 (0x42bf80)
    gopanic: reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
 C:/Go/src/reflect/type.go:955 (0x4bdb19)
    (*rtype).Elem: panic("reflect: Elem of invalid type")
   C:/Learnings/Go/src/     (0x8b6b5a)
    mapForm: typ := reflect.TypeOf(ptr).Elem()
    formBinding.Bind: if err := mapForm(obj, req.Form); err != nil {
  <autogenerated>:1 (0x8b9298)
  C:/Learnings/Go/src/ (0x8f3319)
    (*Context).ShouldBindWith: return b.Bind(c.Request, obj)
  C:/Learnings/Go/src/ (0x8f2e3d)
    (*Context).MustBindWith: if err = c.ShouldBindWith(obj, b); err != nil {
    C:/Learnings/Go/src/ (0x8f2a7d)
    (*Context).Bind: return c.MustBindWith(obj, b)
    C:/Learnings/Go/src/AuthenticateService/jwtsecuritytoken/jwtsecuritytoken.go:22 (0x905c23)
    GenerateToken: err := c.Bind(reqBody)
  C:/Learnings/Go/src/ (0x8f10b9)
    (*Context).Next: c.handlers[c.index](c)
  C:/Learnings/Go/src/ (0x9038f0)
    RecoveryWithWriter.func1: c.Next()
  C:/Learnings/Go/src/ (0x8f10b9)
    (*Context).Next: c.handlers[c.index](c)
  C:/Learnings/Go/src/ (0x902c12)
    LoggerWithWriter.func1: c.Next()
  C:/Learnings/Go/src/ (0x8f10b9)
    (*Context).Next: c.handlers[c.index](c)
  C:/Learnings/Go/src/ (0x8fa52c)
    (*Engine).handleHTTPRequest: c.Next()
  C:/Learnings/Go/src/ (0x8f9cb1)
    (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
  C:/Go/src/net/http/server.go:2619 (0x66b69a)
     serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
  C:/Go/src/net/http/server.go:1801 (0x6676c3)
    (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
   C:/Go/src/runtime/asm_amd64.s:2337 (0x457e70)
    goexit: BYTE    $0x90   // NOP
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dopq87915
    dopq87915 2017-12-16 10:24

    I guess, instead of

    var reqBody requestBody
    err := c.Bind(reqBody)

    might be

    reqBody := new(requestBody)
    err := c.Bind(reqBody)

    second code creates a pointer to requestBody, so Bind can apply to a pointer. If you pass a value it can bind, but you won t get the results. So it is invalid type. More concretely speaking at mapForm: typ := reflect.TypeOf(ptr).Elem() it takes the type, assumes it is a pointer to something (Elem()). When you pass in a value Elem() panics see

    Why new() and not var reqBody *requestBody. new will create a new object to bind values on. Declaring the pointer in the second case will create a nil pointer, non bindable.

    You might also write reqBody := &requestBody{}, that would be the same as the new syntax

    点赞 评论