在Go的http包中,如何获取POST请求的查询字符串?

165

我正在使用 Go 语言的 http 包处理 POST 请求。如何从 Request 对象中访问和解析查询字符串的内容?我在官方文档中没有找到答案。

如何使用 Go 语言的 http 包处理 POST 请求?如何从 Request 对象中访问和解析查询字符串的内容?我在官方文档中找不到答案。


有一件事需要记住,如果你正在使用cURL发送请求并且使用r.FormValue("id")来获取查询参数,那么你不能通过cURL的表单数据发送它(例如,curl 0.0.0.0:8888 -d id=foobar将不起作用)。你必须通过查询参数发送它(curl 0.0.0.0:8888?id=foobar)。 - user427390
6个回答

189

以下是如何访问GET参数的更具体示例。 Request对象有一个名为Query的方法,可以为您解析它们:

假设请求URL如下:http://host:port/something?param1=b

func newHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Println("GET params were:", r.URL.Query())

  // if only one expected
  param1 := r.URL.Query().Get("param1")
  if param1 != "" {
    // ... process it, will be the first (only) if multiple were given
    // note: if they pass in like ?param1=&param2= param1 will also be "" :|
  }

  // if multiples possible, or to process empty values like param1 in
  // ?param1=&param2=something
  param1s := r.URL.Query()["param1"]
  if len(param1s) > 0 {
    // ... process them ... or you could just iterate over them without a check
    // this way you can also tell if they passed in the parameter as the empty string
    // it will be an element of the array that is the empty string
  }    
}

还要注意,“Values映射中的键[即Query()返回值中的键]区分大小写。”


4
之前的答案已经提到并链接到文档,介绍了如何做到这一点(如果所需的字段不存在会导致越界切片引用的例子将引发 panic,请使用 r.URL.Query().Get("moviename") 避免这种致命错误)。 - Dave C
2
感谢提供信息。是的,对我来说文档有点混乱,所以我发布了这个作为一个“实际例子”,以防有用。修复了空值检查。如果有多个,则仅使用Get方法返回第一个,因此这是更多示例。有用的信息,谢谢! - rogerdpack
另外,我认为您不能将字符串与nil进行比较:http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/,即string!=“”是有效的。 - James Milner
我认为如果示例完整的话,那段代码不会编译。你不能将Values.Get()返回的空字符串与nil进行比较。 https://golang.org/pkg/net/url/#Values - erik258

180
一个查询字符串,按定义, 在URL中。您可以使用req.URL (doc)访问请求的URL。URL对象具有一个Query()方法(doc),该方法返回一个Values类型,这只是一个QueryString参数的map[string][]string
如果您需要获取由HTML表单提交的POST数据as submitted by an HTML form,那么这通常是请求正文中的键值对。您在回答中使用ParseForm()方法调用并使用req.Form字段获取键值对映射是正确的,但您也可以调用FormValue(key)方法来获取特定键的值。这会在需要时调用ParseForm()方法,并获取无论是以查询字符串还是请求正文的方式发送的值。

2
我发现'req.FormValue(key)'方法更快,并且可以为您执行所有必要的代码来预解析URL。 - OnlyAngel
11
如果有所帮助,req.URL.RawQuery 返回 GET 请求中问号后的所有内容。 - kouton
我发现很有趣的是,除非至少调用一次req.formValue("some_field"),否则req.Form为空数组。 - user1663023

21

以下是一个例子:

value := r.FormValue("field")

了解有关HTTP包的更多信息,您可以访问其文档此处FormValue基本上按照POST或PUT值或GET值的顺序返回第一个找到的值。


10

9
以下是一个简单可用的例子:
package main

import (
    "io"
    "net/http"
)
func queryParamDisplayHandler(res http.ResponseWriter, req *http.Request) {
    io.WriteString(res, "name: "+req.FormValue("name"))
    io.WriteString(res, "\nphone: "+req.FormValue("phone"))
}

func main() {
    http.HandleFunc("/example", func(res http.ResponseWriter, req *http.Request) {
        queryParamDisplayHandler(res, req)
    })
    println("Enter this in your browser:  http://localhost:8080/example?name=jenny&phone=867-5309")
    http.ListenAndServe(":8080", nil)
}

enter image description here


6

以下文字来自官方文档。

Form 包含解析后的表单数据,包括 URL 字段的查询参数POST 或 PUT 表单数据。只有在调用 ParseForm 后才能使用此字段。

因此,以下示例代码将起作用。

func parseRequest(req *http.Request) error {
    var err error

    if err = req.ParseForm(); err != nil {
        log.Error("Error parsing form: %s", err)
        return err
    }

    _ = req.Form.Get("xxx")

    return nil
}

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