Go语言提供了一个功能丰富的net/http包,它提供了客户端和服务端的实现,使得我们可以比较轻易的创建http服务。
创建一个简单的http服务
//step1. 建立 URL:Handler映射表
servemux := http.NewServeMux()
servemux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, world")
})
//step2. 创建并运行HTTP server
server := http.Server{Addr: ":8080", Handler: mux}
log.Fatal(server.ListenAndServe())
除了上面我们使用http.NewServeMux创建一个mux然后再调用HandleFunc外我们可以也可以这样使用
//直接调用http的Handle方法
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, world")
})
//Handle函数原型
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = &defaultServeMux
var defaultServeMux ServeMux
HandleFunc其实也是调用了ServeMux的HandleFunc方法,只是使用了DefaultServeMux这个默认实例的用法,这种使用方式在其他库也是常见的一种方式
Client
Client类型代表HTTP客户端。它的零值(DefaultClient)是一个可用的使用DefaultTransport的客户端,这里其实跟DefaultServeMux一样的实现方。
我们也可以自己实例化一个client
client := &http.Client{
//指定处理重定向的策略
CheckRedirect: redirectPolicyFunc,
//指定本类型的值执行请求的时间限制
Timeout:30,
}
//发送Get请求
resp, err := client.Get("http://example.com")
不过不管是使用默认还是自己实例化client,底层都是调用do方法,然后基于do方法做Get/Post/PostForm的上层封装。PostForm的话是提交表单,url.Values类型的data会被编码为请求的主体。Post数据的类型一般会设为"application/x-www-form-urlencoded"。
resp, err := http.PostForm("http://example.com/form",
url.Values{"key": {"Value"}, "id": {"123"}})
//实际调用方法,Get/Post都是基于do方法做的封装
func (c *Client) do(req *Request) (retres *Response, reterr error) {
上层对do方法的封装主要体现在对Request结构传递的不同,比如设置Request的Method(请求方式Get、Post),具体的Request结构体的可以在net/http/client.go看到。
Request结构
Request类型代表一个服务端接受到的或者客户端发送出去的HTTP请求,在Client发送请求是,也会传递一个request。
之前遇到一个怎么在request(请求)中可以使用下面方式获取client使用PostForm发送请求参数的问题,可以用到下面这种方式。
//ParseForm解析URL中的查询字符串,并将解析结果更新到r.Form字段,也就是 url.Values
func (r *Request) ParseForm() error
//接收经过ParseForm的值
func (r *Request) FormValue(key string) string
func (r *Request) PostFormValue(key string) string
文件上传的话使用Fromfile
//FormFile返回以key为键查询r.MultipartForm字段得到结果中的第一个文件和它的信息
func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error)
Response结构
Response代表一个HTTP请求的回复,该结构主要有比如StatusCode状态码、Body回复主体等信息
type Response struct {
Status string // 例如"200 OK"
StatusCode int // 例如200
Proto string // 例如"HTTP/1.0"
ProtoMajor int // 例如1
ProtoMinor int // 例如0
Header Header // Header保管头域的键值对。
Body io.ReadCloser // Body代表回复的主体。
ContentLength int64 // ContentLength记录相关内容的长度。
TransferEncoding []string // 按从最外到最里的顺序列出传输编码
Close bool //Close记录头域是否指定应在读取完主体后关闭连接
Trailer Header //Trailer字段保存和头域相同格式的trailer键值对
Request *Request // Request是用来获取此回复的请求
TLS *tls.ConnectionState // TLS包含接收到该回复的TLS连接的信息
}
总结
net/http包我们在日常开发中长会用到的一些使用大概描述了一下,比如怎么创建一个web服务,发送请求调用do方法,request和response的结构等。后面打算分享下自己对处理http请求流程的理解,哈哈,先抛出几个问题:ServeHttp是什么,如果我们想实现自己的处理逻辑该怎么做,接口动态转发