建议看这篇文章前先看一下net/http文档 http://golang.org/pkg/net/http/html
net.http包里面有不少文件,都是和http协议相关的,好比设置cookie,header等。其中最重要的一个文件就是server.go了,这里咱们阅读的就是这个文件。golang
ResponseWriter: 生成Response的接口缓存
Handler: 处理请求和生成返回的接口cookie
ServeMux: 路由,后面会说到ServeMux也是一种Handler网络
Conn : 网络链接并发
实现了handler接口的对象就意味着往server端添加了处理请求的逻辑。函数
type Handler interface { ServeHTTP(ResponseWriter, *Request) // 具体的逻辑函数 }
下面是三个接口(ResponseWriter, Flusher, Hijacker):google
// ResponseWriter的做用是被Handler调用来组装返回的Response的 type ResponseWriter interface { // 这个方法返回Response返回的Header供读写 Header() Header // 这个方法写Response的Body Write([]byte) (int, error) // 这个方法根据HTTP State Code来写Response的Header WriteHeader(int) } // Flusher的做用是被Handler调用来将写缓存中的数据推给客户端 type Flusher interface { // 这个方法将写缓存中数据推送给客户端 Flush() } // Hijacker的做用是被Handler调用来关闭链接的 type Hijacker interface { // 这个方法让调用者主动管理链接 Hijack() (net.Conn, *bufio.ReadWriter, error) }
实现这三个接口的结构是response(这个结构是http包私有的,在文档中并无显示,须要去看源码)spa
// response包含了全部server端的http返回信息 type response struct { conn *conn // 保存这次HTTP链接的信息 req *Request // 对应请求信息 chunking bool // 是否使用chunk wroteHeader bool // header是否已经执行过写操做 wroteContinue bool // 100 Continue response was written header Header // 返回的http的Header written int64 // Body的字节数 contentLength int64 // Content长度 status int // HTTP状态 needSniff bool // 是否须要使用sniff。(当没有设置Content-Type的时候,开启sniff能根据HTTP body来肯定Content-Type) closeAfterReply bool //是否保持长连接。若是客户端发送的请求中connection有keep-alive,这个字段就设置为false。 requestBodyLimitHit bool //是否requestBody太大了(当requestBody太大的时候,response是会返回411状态的,并把链接关闭) }
在response中是能够看到设计
func (w *response) Header() Header func (w *response) WriteHeader(code int) func (w *response) Write(data []byte) (n int, err error) func (w *response) Flush() func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error)
这么几个方法。因此说response实现了ResponseWriter,Flusher,Hijacker这三个接口
handlerFunc是常常使用到的一个type
type HandlerFunc func(ResponseWriter, *Request) // ServeHTTP calls f(w, r). func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) }
这里须要多回味一下了,这个HandlerFunc定义和ServeHTTP合起来是说明了什么?说明HandlerFunc的全部实例是实现了ServeHttp方法的。另,实现了ServeHttp方法就是什么?实现了接口Handler!
因此你之后会看到不少这样的句子:
func AdminHandler(w ResponseWriter, r *Request) { ... } handler := HandlerFunc(AdminHandler) handler.ServeHttp(w,r)
请不要讶异,你明明没有写ServeHttp,怎么能调用呢? 实际上调用ServeHttp就是调用AdminHandler。
HandlerFunc(AdminHandler)是一个转换而非一个函数调用,由于http.HandlerFunc是一个类型。HandlerFunc显示了在Go语言接口机制中一些不一样寻常的特色。这是一个有实现了接口http.Handler方法的函数类型。ServeHTTP方法的行为调用了它自己的函数。所以HandlerFunc是一个让函数值知足一个接口的适配器(此处是http.Handler接口适配器,由于serverHTTP实现了Handler接口),这里函数和这个接口仅有的方法有相同的函数签名。实际上,这个技巧让一个单一的类型例如MyHandler以多种方式知足http.Handler接口。
附带上一个play.google写的一个小例子
http://play.golang.org/p/nSt_wcjc2u
有兴趣继续研究的同窗能够继续试验下去
下面接着看Server.go
它就是http包中的路由规则器。你能够在ServerMux中注册你的路由规则,当有请求到来的时候,根据这些路由规则来判断将请求分发到哪一个处理器(Handler)。
它的结构以下:
type ServeMux struct { mu sync.RWMutex //锁,因为请求设计到并发处理,所以这里须要一个锁机制 m map[string]muxEntry // 路由规则,一个string对应一个mux实体,这里的string就是我注册的路由表达式 }
下面看一下muxEntry
type muxEntry struct { explicit bool // 是否精确匹配 h Handler // 这个路由表达式对应哪一个handler }
看到这两个结构就应该对请求是如何路由的有思路了:
ServeMux定义的方法有:
func (mux *ServeMux) match(path string) Handler //根据path获取Handler func (mux *ServeMux) handler(r *Request) Handler //根据Request获取Handler,内部实现调用match func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) //!!这个说明,ServeHttp也实现了Handler接口,它实际上也是一个Handler!内部实现调用handler func (mux *ServeMux) Handle(pattern string, handler Handler) //注册handler方法 func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) //注册handler方法(直接使用func注册)
在godoc文档中常常见到的DefaultServeMux是http默认使用的ServeMux
var DefaultServeMux = NewServeMux()
若是咱们没有自定义ServeMux,系统默认使用这个ServeMux。
换句话说,http包外层(非ServeMux)中提供的几个方法:
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) } func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { DefaultServeMux.HandleFunc(pattern, handler) }
实际上就是调用ServeMux结构内部对应的方法。
下面还剩下一个Server结构
type Server struct { Addr string // 监听的地址和端口 Handler Handler // 全部请求须要调用的Handler(实际上这里说是ServeMux更确切)若是为空则设置为DefaultServeMux ReadTimeout time.Duration // 读的最大Timeout时间 WriteTimeout time.Duration // 写的最大Timeout时间 MaxHeaderBytes int // 请求头的最大长度 TLSConfig *tls.Config // 配置TLS }
Server提供的方法有:
func (srv *Server) Serve(l net.Listener) error //对某个端口进行监听,里面就是调用for进行accept的处理了 func (srv *Server) ListenAndServe() error //开启http server服务,内部调用Serve func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error //开启https server服务,内部调用Serve
固然Http包也直接提供了方法供外部使用,实际上内部就是实例化一个Server,而后调用ListenAndServe方法
func ListenAndServe(addr string, handler Handler) error //开启Http服务 func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error //开启HTTPs服务
参考:http://www.cnblogs.com/yjf512/archive/2012/08/22/2650873.html