Go 发起 HTTP 请求及获取相关参数
Get 请求
Get 请求可以直接 http.Get 方法,非常简单。func httpGet() {
resp, err := http.Get("http://www.01happy.com/demo/accept.php?id=1")
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle error
}
fmt.Println(string(body))
}
Post 请求
一种是使用 http.Post 方式func httpPost() {
resp, err := http.Post("http://www.01happy.com/demo/accept.php",
"application/x-www-form-urlencoded",
strings.NewReader("name=cjb"))
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle error
}
fmt.Println(string(body))
}
Tips:使用这个方法的话,第二个参数要设置成 "application/x-www-form-urlencoded",否则 Post 参数无法传递。
一种是使用http.PostForm方法
func httpPostForm() {
resp, err := http.PostForm("http://www.01happy.com/demo/accept.php",
url.Values{"key": {"Value"}, "id": {"123"}})
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle error
}
fmt.Println(string(body))
}
复杂的请求
有时需要在请求的时候设置 头参数,cookie 之类的数据,就可以使用 http.Do 方法。func httpDo() {
client := &http.Client{}
req, err := http.NewRequest("POST", "http://www.01happy.com/demo/accept.php", strings.NewReader("name=cjb"))
if err != nil {
// handle error
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Cookie", "name=anny")
resp, err := client.Do(req)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle error
}
fmt.Println(string(body))
}
同上面的 Post 请求,必须要设定 Content-Type 为 application/x-www-form-urlencoded,Post 参数才可正常传递。如果要发起 head 请求可以直接使用 http client 的 head 方法,比较简单,这里就不再说明。
Go Web 开发获取 Get、Post、Cookie 参数:
在成熟的语言 Java、Python、PHP 要获取这些参数应该来讲都非常简单,过较新的语言golang用获取这些个参数还是费了不少劲,特此记录一下。
在贴代码之前如果能先理解一下 Go http.request 的三个属性 Form、PostForm、MultipartForm 应该能较好的理解代码,下面摘录一下。
Form PostForm MultipartForm 简要说明一下:
Form:存储了 Post、Put 和 Get 参数,在使用之前需要调用 ParseForm 方法。
PostForm:存储了 Post、Put 参数,在使用之前需要调用 ParseForm 方法。
MultipartForm:存储了包含了文件上传的表单的 Post 参数,在使用前需要调用 ParseMultipartForm 方法。
获取GET参数
网上比较常见的一个版本是:r.ParseForm()
if len(r.Form["id"]) > 0 {
fmt.Fprintln(w, r.Form["id"][0])
}
其中 r 表示 *http.Request 类型,w 表示 http.ResponseWriter 类型。
r.Form 是 url.Values 字典类型,r.Form["id"] 取到的是一个数组类型。因为 http.request 在解析参数的时候会将同名的参数都放进同一个数组里,所以这里要用[0]获取到第一个。
这种取法在通常情况下都没有问题,但是如果是如下请求则无法取到需要的值:
<form action="http://localhost:9090/?id=1" method="POST">
<input type="text" name="id" value="2" />
<input type="submit" value="submit" />
</form>
因为r.Form包含了get和post参数,并且以 Post 参数为先,上例post参数和get参数都有id,所以应当会取到 Post 参数2。虽然这种情况并不多见,但是从严谨的角度来看程序上还是应当处理这种情况。立马补上改进代码:
queryForm, err := url.ParseQuery(r.URL.RawQuery)
if err == nil && len(queryForm["id"]) > 0 {
fmt.Fprintln(w, queryForm["id"][0])
}
代码比较简单,就是分析 url 问号后的参数。事实上这个也是标准库 ParseForm 中关于 Get 参数解析代码。
获取POST参数
这里要分两种情况:普通的 Post 表单请求,Content-Type=application/x-www-form-urlencoded
有文件上传的表单,Content-Type=multipart/form-data
第一种情况比较简单,直接用 PostFormValue 就可以取到了。
fmt.Fprintln(w, r.PostFormValue("id"))
第二种情况复杂一些,如下表单:
<form action="http://localhost:9090" method="POST" enctype="multipart/form-data">
<input type="text" name="id" value="2" />
<input type="file" name="pic" />
<input type="submit" value="submit" />
</form>
因为需要上传文件,所以表单enctype要设置成 multipart/form-data。此时无法通过 PostFormValue 来获取id的值,因为 Go 库里还未实现这个方法:
Go 中不能用 PostForm 获取 Post 参数
幸好 Go 中可以提供了另外一个属性 MultipartForm 来处理这种情况。
r.ParseMultipartForm(32 << 20)
if r.MultipartForm != nil {
values := r.MultipartForm.Value["id"]
if len(values) > 0 {
fmt.Fprintln(w, values[0])
}
}
感谢:在测试post的时候,一开始都是以第二种情况来测试的,所以造成了一个误区以为 PostFormValue 无法取到值。这里感谢 @九头蛇龙 的纠正。
获取COOKIE参数
cookie, err := r.Cookie("id")if err == nil {
fmt.Fprintln(w, "Domain:", cookie.Domain)
fmt.Fprintln(w, "Expires:", cookie.Expires)
fmt.Fprintln(w, "Name:", cookie.Name)
fmt.Fprintln(w, "Value:", cookie.Value)
}
r.Cookie返回*http.Cookie类型,可以获取到domain、过期时间、值等数据。
小结
在折腾的过程中看了下 net/http 包中的源码,感觉在web开发中还是有很多不完善的地方。作为使用者来讲,最希望就是直接通过一个方法取到相应的值就可以了,期待官方团队尽早完善。
哇~~~ 竟然还没有评论!