请求和响应的主体都由Request
结构的Body
字段表示,这个字段是一个io.Read Closer
接口,该接口既包含了Reader
接口,也包含了Closer
接口。
其中Reader
接口拥有Read
方法,这个方法接受一个字节切片为输入,并在执行之后返回被读取内容的字节数以及一个可选的错误作为结果;
Closer
接口则拥有Close
方法,这个方法不接受任何参数,但会在出错时返回一个错误。同时包含Reader
接口和Closer
接口意味着用户可以对Body
字段调用Read
方法和Close
方法。作为例子,代码清单4-3展示了如何使用Read
方法读取请求主体的内容。
代码清单4-3 读取请求主体中的数据
package main
import(
"fmt"
"net/http"
)
func body(w http.ResponseWriter, r *http.Request) {
len := r.ContentLength
body := make([]byte, len)
r.Body.Read(body)
fmt.Fprintln(w,string(body))
}
func main(){
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/body",body)
server.ListenAndServe()
}
这段程序首先通过ContentLength
方法获取主体数据的字节长度,接着根据这个长度创建一个字节数组,然后调用Read
方法将主体数据读取到字节数组中。
因为GET
请求并不包含报文主体,所以如果我们想要测试这个服务器,就需要给它发送POST
请求。
正如之前所说,浏览器一般需要通过HTML表单才能发送POST
请求,但是因为本书在下一节才会开始介绍HTML表单,所以这里我们暂且就先使用HTTP客户端来测试服务器。市面上可用的HTTP客户端非常多,既有桌面版的图形HTTP客户端,也有浏览器插件或者扩展,还有curl
等命令行程序可供选择。
作为例子,以下命令展示了如何使用curl
向服务器发送一条POST请求:
$ curl -id "first_name=sausheong&last_name=chang" 127.0.0.1:8080/body
curl
在接收到响应之后将向用户返回一段完整并且未经处理的HTTP响应,其中位于空行之后的就是HTTP的主体。以下展示的就是上面的curl
命令返回的响应:
HTTP/1.1 200 OK
Date: Tue, 13 Jan 2015 16:11:58 GMT
Content-Length: 37
Content-Type: text/plain; charset=utf-8
first_name=sausheong&last_name=chang
因为Go语言提供了诸如FormValue
和FormFile
这样的方法来提取通过POST方法提交的表单,所以用户一般不需要自行读取主体中未经处理的表单,本章接下来的一节就会介绍FormValue
和FormFile
等方法。