1.net/http创建一个服务
package main
import (
"net/http"
)
func main() {
http.Handle("/user", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte("I am user interface"))
}))
http.Handle("/job", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte("I am job interface"))
}))
http.ListenAndServe(":8080", nil) // 当前此处为空,对应服务的请求只根据如上注册的接口方法来进行接受处理
}
2.net/http启动一个服务的解析过程
如上图先通过http.hadnle,将自己所需的接口方法按照http.HadnlerFunc的类型方法进行注册。再通过 http.ListenAndServe(":8080", nil)启动服务即可,非常的简单粗暴。
3.解析2中的关键方法源码
? 3.1 http.HandlerFunc类型?,源代码的定义类型如下:
// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
如上方法的DefaultServeMux为结构为如下图:
var DefaultServeMux = &defaultServeMux
var defaultServeMux ServeMux
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
es []muxEntry // slice of entries sorted from longest to shortest.
hosts bool // whether any patterns contain hostnames
}
ServeMux结构实现了HandleFunc的方法。并且ServeMux实现了Handle方法并将对应的url跟相应方法注册到对应上图的m中:
// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
func (mux *ServeMux) Handle(pattern string, handler Handler) {
mux.mu.Lock()
defer mux.mu.Unlock()
if pattern == "" {
panic("http: invalid pattern")
}
if handler == nil {
panic("http: nil handler")
}
if _, exist := mux.m[pattern]; exist {
panic("http: multiple registrations for " + pattern)
}
if mux.m == nil {
mux.m = make(map[string]muxEntry)
}
e := muxEntry{h: handler, pattern: pattern}
mux.m[pattern] = e
if pattern[len(pattern)-1] == '/' {
mux.es = appendSorted(mux.es, e)
}
if pattern[0] != '/' {
mux.hosts = true
}
}
?3.2 启动一个服务过程
设置对应的结构体信息
type Server struct {
Addr string
Handler Handler // handler to invoke, http.DefaultServeMux if nil
...
}
func (srv *Server) ListenAndServe() error {
if srv.shuttingDown() {
return ErrServerClosed
}
addr := srv.Addr
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(ln)
}
如上图,启动服务是,会监听一个端口,并且每当接受一个请求时,会启动一个协程来处此请求,如下代码:
func (srv *Server) Serve(l net.Listener) error {
....
for {
rw, err := l.Accept()
....
....
c := srv.newConn(rw)
c.setState(c.rwc, StateNew) // before Serve can return
go c.serve(connCtx) // 启动一个协程序来处理接受的请求
}
}
启动的协程内部通过如下结构调用:
type serverHandler struct {
srv *Server
}
// 具体的实现方法调用处理
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler
if handler == nil {
handler = DefaultServeMux // 该处因未定义对应接收结构处理方法,故此使用默认创建的结构方法。
}
if req.RequestURI == "*" && req.Method == "OPTIONS" {
handler = globalOptionsHandler{}
}
handler.ServeHTTP(rw, req)
}
// 如下DefaultServeMux结构的方法,如下:
// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
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) // 利用接收的url等信息,查找注册的相应方法进行数据处理。
h.ServeHTTP(w, r)
}
// 找到注册的响应函数,并执行
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
|