-3
 func MakeMap(w http.ResponseWriter, r *http.Request) {
    // userInfo := context.Get(r, "userInfo").(model.User)
    type _getData struct {
        Title string   `json:"title"`
        Tag   []string `json:"tag"`
    }
    var getData _getData
    err := json.NewDecoder(r.Body).Decode(&getData)
    if err != nil {
        panic(err.Error())
    }
    fmt.Print(getData)

}

When I run the above code, I get the following error

2021/08/24 13:56:54 http: panic serving 127.0.0.1:50619: runtime error: invalid memory address or nil pointer dereference
goroutine 23 [running]:
net/http.(*conn).serve.func1(0x140001e9180)
        /usr/local/go/src/net/http/server.go:1824 +0x108
panic(0x10505b860, 0x10522f240)
        /usr/local/go/src/runtime/panic.go:971 +0x3f4
traveling/controller/mapController.MakeMap(0x1050b5630, 0x140001f40e0, 0x1400018aa00)
/Users/choeyunseog/traveling/traveling/controller/mapController/mapController.go:20 +0x3c

I've just started studying, I'm not sure why I'm having this problem, please help

enter image description here

err := json.NewDecoder(r.Body).Decode(&getData) 

I get the following error when i change code line 20 like above

 2021/08/24 14:16:44 http: panic serving 127.0.0.1:51396: invalid character '-' in numeric literal
goroutine 23 [running]:
net/http.(*conn).serve.func1(0x140001e9360)
        /usr/local/go/src/net/http/server.go:1824 +0x108
panic(0x100d85d00, 0x14000206070)
        /usr/local/go/src/runtime/panic.go:971 +0x3f4
traveling/controller/mapController.MakeMap(0x100df1630, 0x140001f40e0, 0x1400018aa00)
        /Users/choeyunseog/traveling/traveling/controller/mapController/mapController.go:24 +0x194
net/http.HandlerFunc.ServeHTTP(0x100de75d8, 0x100df1630, 0x140001f40e0, 0x1400018aa00)
        /usr/local/go/src/net/http/server.go:2069 +0x40
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Choi yun seok
  • 309
  • 2
  • 15

2 Answers2

1

To get the multipart form data from a POST/PUT/PATCH request's body you can use the ParseMultipartForm method to parse the body and then access the data through the PostForm field. Or you can use FormValue to get just the first value associated with the form's field.

maxMemory := 32<<20
if err := r.ParseMultipartForm(maxMemory); err != nil {
    panic(err)
}

fmt.Println(_getData{
    Title: r.FormValue("title"), // FormValue returns string
    Tag:   r.PostForm["tag[]"],  // PostForm is a map of []string
})
mkopriva
  • 35,176
  • 4
  • 57
  • 71
  • i try type _getData struct { Title string `json:"title"` Tag []string `json:"tag"` } var getData _getData getData.Tag = r.FormValue("tag[]") and get error like this cannot use r.FormValue("tag[]") (value of type string) as []string value in assignment – Choi yun seok Aug 24 '21 at 05:45
  • I know, what I want is, when sending multiple pieces of information like tag[] in postman, I wonder how to receive this data as an array in golang – Choi yun seok Aug 24 '21 at 05:51
  • Thanks, all problems are solved, but var getData _getData getData.Tag = r.PostForm["tag[]"] getData.Title = r.FormValue("title") When I use it like below, I do not receive an array value, what is the reason? – Choi yun seok Aug 24 '21 at 05:57
  • I didn't write about r.ParseForm(), I'm really sorry but can you show me a simple example of how r.ParseForm() should be used I'm really sorry – Choi yun seok Aug 24 '21 at 06:05
  • type _getData struct { Title string `json:"title"` Tag []string `json:"tag"` } if err := r.ParseForm(); err != nil { panic(err) } var getData _getData getData.Tag = r.PostForm["tag[]"] getData.Title = r.FormValue("title") fmt.Print(getData) – Choi yun seok Aug 24 '21 at 06:10
  • I wrote the above the result is still { []} is – Choi yun seok Aug 24 '21 at 06:11
  • @Choiyunseok my mistake, I mixed up `multipart/form-data` with `form-urlencoded`. See updated answer. – mkopriva Aug 24 '21 at 06:21
  • Everything worked out, thank you very much, thank you so much – Choi yun seok Aug 24 '21 at 06:28
0

You can use to parse form data into json like annotated struct using package github.com/senpathi/paramex. Struct fields must be annotated with param keyword and tag name is key of the form data.

your struct should be as below.

type _getData struct {
        Title string   `param:"title"`
        Tag   []string `param:"tag[]"`
    }

This is the updated MakeMap handler function for your postman request mentioned in the question

func MakeMap(w http.ResponseWriter, r *http.Request) {
    // userInfo := context.Get(r, "userInfo").(model.User)
    type _getData struct {
        Title string   `param:"title"`
        Tag   []string `param:"tag[]"`
    }

    // this needed because u send data from Postman as multipart/form-data
    maxMemory := 32<<20
    if err := r.ParseMultipartForm(int64(maxMemory)); err != nil {
        panic(err)
    }

    var getData _getData

    extractor := paramex.NewParamExtractor()
    err := extractor.ExtractForms(&getData, r)
    if err != nil {
        panic(err.Error())
    }

    fmt.Print(getData)
    //Output: {defaultMap [travelling travelling2]}
}
nipuna
  • 3,697
  • 11
  • 24