如何在Go服务器中提取POST参数

23

以下是用 Go 编写的服务器。

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
    fmt.Fprintf(w,"%s",r.Method)
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

我如何提取发送到localhost:8080/something URL的POST数据?

7个回答

39

就像这样:

func handler(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()                     // Parses the request body
    x := r.Form.Get("parameter_name") // x will be "" if parameter is not set
    fmt.Println(x)
}

1
请注意,这似乎仅适用于urlencoded而不是multipart表单数据。 - CubanAzcuy
6
这份文档目前非常简陋,缺乏好的示例。https://golang.org/pkg/net/http/ 只是说一下... - frederix
1
是的,那种 PS 是不必要的。 - franck

7
http.Request的文档中引用:
// Form contains the parsed form data, including both the URL
// field's query parameters and the POST or PUT form data.
// This field is only available after ParseForm is called.
// The HTTP client ignores Form and uses Body instead.
Form url.Values

6
请举个例子让说明更具体些,我是新手,不太懂如何使用它。 - footy

4

对于 POSTPATCHPUT 请求:

我们首先调用 r.ParseForm(),将 POST 请求体中的任何数据添加到 r.PostForm 映射中。

err := r.ParseForm()
if err != nil {
    // in case of any error
    return
}

// Use the r.PostForm.Get() method to retrieve the relevant data fields
// from the r.PostForm map.
value := r.PostForm.Get("parameter_name")

对于所有请求,包括POSTGETPUT等:

err := r.ParseForm()
if err != nil {
    // in case of any error
    return
}

// Use the r.Form.Get() method to retrieve the relevant data fields
// from the r.Form map.
value := r.Form.Get("parameter_name") // attention! r.Form, not r.PostForm 

表单(Form)方法

相比之下,r.Form 映射是为所有请求填充的(不考虑它们的 HTTP 方法),并且包含来自任何请求正文和任何查询字符串参数的表单数据。因此,如果我们的表单被提交到 /snippet/create?foo=bar,我们也可以通过调用 r.Form.Get("foo") 来获取 foo 参数的值。请注意,在冲突的情况下,请求正文值将优先于查询字符串参数。

FormValue 和 PostFormValue 方法

net/http 包还提供了 r.FormValue() 和 r.PostFormValue() 方法。这些本质上是快捷方式函数,它们会为您调用 r.ParseForm(),然后从 r.Form 或 r.PostForm 中提取相应的字段值。我建议避免使用这些快捷方式,因为它们会默默地忽略 r.ParseForm() 返回的任何错误。这并不理想——这意味着我们的应用程序可能会因为错误而在用户端失败,但没有反馈机制来让他们知道。

所有示例都来自于最好的关于 Go 的书籍 - Let's Go! Learn to Build Professional Web Applications With Golang。这本书可以回答你所有的问题!


3
为从post请求中提取值,您需要首先调用r.ParseForm()方法。[这个][1]方法会解析来自URL的原始查询,并更新r.Form。
对于POST或PUT请求,它还会将请求体解析为一个表单,并将结果放入r.PostForm和r.Form两个参数中。POST和PUT请求的body参数优先于URL查询字符串中的值,存储在r.Form参数中。
现在,您的r.From是客户端提供的所有值的映射。要提取特定值,您可以使用r.FormValue("<your param name>")r.Form.Get("<your param name>")方法。
您也可以使用r.PostFormValue方法。

0
package main

import (
  "fmt"
  "log"
  "net/http"
  "strings"
)


func main() {
  // the forward slash at the end is important for path parameters:
  http.HandleFunc("/testendpoint/", testendpoint)
  err := http.ListenAndServe(":8888", nil)
  if err != nil {
    log.Println("ListenAndServe: ", err)
  }
}

func testendpoint(w http.ResponseWriter, r *http.Request) {
  // If you want a good line of code to get both query or form parameters
  // you can do the following:
  param1 := r.FormValue("param1")
  fmt.Fprintf( w, "Parameter1:  %s ", param1)

  //to get a path parameter using the standard library simply
  param2 := strings.Split(r.URL.Path, "/")

  // make sure you handle the lack of path parameters
  if len(param2) > 4 {
    fmt.Fprintf( w, " Parameter2:  %s", param2[5])
  }
}

您可以在aapi playground 这里运行代码

将此添加到您的访问URL中:/mypathparameeter?param1=myqueryparam

我想现在留下上面的链接,因为它为您提供了一个很好的运行代码的地方,而且我相信能够看到它的实际效果是有帮助的,但是让我解释一些典型情况,您可能需要一个post参数。

开发人员通常会使用多部分表单数据从请求中提取文件或大量数据时,将其发送到后端服务器。因此,在问题的上下文中,我不认为这与本题相关。他正在寻找通常意味着表单提交数据的post参数。通常,表单提交参数会被发送到后端服务器。

当用户从HTML向golang提交登录表单或注册数据时,客户端发送的内容类型标头通常为application/x-www-form-urlencoded,这是问题所询问的,这些将是表单POST参数,并使用r.FormValue("param1")提取。
在从post请求体中获取json的情况下,您将获取整个post请求体并将原始json解组到结构体中,或者在从请求体中提取数据后使用库解析数据,内容类型标头为application/json。
内容类型标头在很大程度上负责解析来自客户端的数据方式,我已经举了2种不同内容类型的示例,但还有许多其他内容类型。

这不是 OP 所问的,他正在询问如何提取 POST 数据。 - Psychotechnopath
编辑所有这些信息到您的答案中,这将是对OP更好的反应。简单的代码片段是不够的,链接答案也有点不受欢迎,因为链接可能会失效/丢失。 - Psychotechnopath
那是很好的建议,我编辑了我的回答,进一步的建议将会很有帮助。我是第一次在这个论坛发帖,想要学习。 - Robert Phillips
@Psychotechnopath,你们可能需要更改这里的陈述https://stackoverflow.com/help/how-to-answer,关于如何回答问题,因为这里说鼓励使用链接。老实说,我认为有时候需要链接来帮助描述。如果我说错了,请告诉我。 - Robert Phillips
但请在链接周围添加上下文,以便您的同行用户了解它是什么以及为什么存在。始终引用重要链接的最相关部分,以防目标站点无法访问或永久离线。我只是说,仅包含链接的答案是不好的。 - Psychotechnopath

0

对于普通请求:

r.ParseForm()
value := r.FormValue("value")

对于多部分请求:

r.ParseForm()
r.ParseMultipartForm(32 << 20)
file, _, _ := r.FormFile("file")

0

只是想要补充一下如何在Go服务器中提取Post参数,如果你正在处理JSON数据的话,这种情况在构建API时经常会遇到...

//...

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)


//While working with JSON in GoLang I prefer using structs so I created the struct here

type JSONData struct {
    // This should contain the expected JSON data
    // <key> <data type> `json: <where to find the data in the JSON` in this case we have
    Name string `json:"name"`
    Age  string `json:"age"`
}

func handler(w http.ResponseWriter, r *http.Request) {
    decoder := json.NewDecoder(r.Body)
    var data JSONData
    error := decoder.Decode(&data)
    if error != nil {
        fmt.Println("Error occured while decoding the data: ", error)
        return
    }
    fmt.Println("name: \t", data.Name, " \n  age: \t ", data.Age)

}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(PORT, nil)
}

// ...
// and the rest of your codes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接