浅析Go语言http服务handler对象底层原理
source link: https://segmentfault.com/a/1190000038547147
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
本文来源于: https://gobea.cn/blog/detail/15zqpwrq.html
最简单的http服务
对于golang
来说,创建一个http服务是轻而易举的事情,如下,我们创建了一个非常简单的http服务,监听8899端口,只提供一个接口返回hello world
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world")
})
http.ListenAndServe(":8899", nil)
}
当你在游览器输入http://127.0.0.1:8899
时,便能看到hello world
的输出
http服务
对于golang
的http服务,我们主要理解两个对象,:
Handler
,它是请求的处理对象,Handler
对象需要实现ServeHTTP
方法,ServeHTTP
执行的是我们的业务逻辑,一般我们定义的func(w http.ResponseWriter, r *http.Request)
的方法需要经过http.HandlerFunc
包装为Handler
对象ServeMux
,它相当于一个路由注册器,保存的请求路径pattern
和Handler
对象的map表,通过pattern
找到对应的Handler
对象,然后执行Handler
对象的ServeHTTP
方法
简单的说,http的执行对象是handler
,而要成为handler
对象.则必须实现ServeHTTP
方法,例如HandlerFunc
实现了ServeHTTP
方法,所以它也是一个handler
对象
handler对象
// Handler接口
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
// HandlerFunc实现了Handler接口
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
server从路由中找到handler
对象,执行handler
对象中的ServeHTTP
方法,也就是说,要作为路由的Handler
对象,需要实现ServeHTTP
方法,有关handler如下:
- handler函数,具有
func(w http.ResponseWriter, r *http.Requests)
签名的函数,需要经过HandlerFunc
函数包装,否则不能作为路由的Handler
对象, - handler处理函数,经过
HandlerFunc
结构包装的handler函数,HandlerFunc
实现了ServeHTTP
接口方法的函数 - handler对象,实现了Handler接口
ServeHTTP
方法的结构
注册路由ServeMux
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
hosts bool
}
type muxEntry struct {
explicit bool
h Handler
pattern string
}
// ServeMux也拥有ServeHTTP方法,也就说ServeMux实现了Handler接口,即ServeMuX其实也是一个Handler对象,不过ServeMux的ServeHTTP方法不是用来处理request和respone,而是用来找到路由注册的handler
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
if r.RequestURI == "*" {
if r.ProtoAtLeast(1, 1) {
w.Header().Set("Connection", "close")
}
w.WriteHeader(StatusBadRequest)
return
}
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
}
如上,ServeMux.m
保存了路由规则pattern
以及对应的Handler
处理对象,另外ServeMux
也拥有ServeHTTP
方法,也就说ServeMux
实现了Handler
接口,即ServeMuX
其实也是一个Handler
对象,不过ServeMux的ServeHTTP方法不是用来处理request和respone,而是用来找到路由注册的handler
package main
import (
"fmt"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world")
})
mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world")
})
http.ListenAndServe(":8899", mux)
}
Server
http.ListenAndServe(":8899",mux)
// 等价于
serv := &http.Server{
Addr: ":8899",
Handler: mux,
}
serv.ListenAndServe()
http.ListenAndServe源码如下:
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK