This is a creation in Article, where the information may have evolved or changed.
In the previous article we passed:
func main() { http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "hello") }) http.ListenAndServe(":9010", nil)}
The relationship between Http.handlefunc routing calls is analyzed. This. Let's analyze HTTP. Listenandserve ():
http.ListenAndServe(addr string, handler Handler)
The internal implementation of the function:
func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe()}
Discover this HTTP. Listenandserve actually calls the Server.listenandserve. Let's look at the structure of the server first:
type Server struct { Addr string // TCP address to listen on, ":http" if empty Handler Handler //处理器,如果为空则使用 http.DefaultServeMux ReadTimeout time.Duration WriteTimeout time.Duration ....}
See this handler, and then contact the last HTTP we analyzed. Handlefunc. We found that they were using HTTP by default. Defaultservemux this route processor. And in this processor we have just saved a route that we have registered. /hello. Then we look at the server. How the Listenandserve is listening and distributing routes.
func (srv *Server) ListenAndServe() error { addr := srv.Addr if addr == "" { addr = ":http" } ln, err := net.Listen("tcp", addr) if err != nil { return err } return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})}
In the server. Listenandserve registered a TCP listener, listening to our registered network port. Then continue calling
server.Serve(l net.Listener) error
For service.
func (srv *Server) Serve(l net.Listener) error { ....... for { rw, e := l.Accept() .... c := srv.newConn(rw) c.setState(c.rwc, StateNew) // before Serve can return go c.serve(ctx) }}
Open a For loop and accept net.accept (). The Srv.newconn (net.conn) is then used to convert a TCP conn into a http.server#conn:
func (srv *Server) newConn(rwc net.Conn) *conn { c := &conn{ server: srv, rwc: rwc, } .... return c}
Finally, a go process is turned on to handle each request.
func (c *conn) serve(ctx context.Context) { // 客户端主机ip c.remoteAddr = c.rwc.RemoteAddr().String() .... // HTTP/1.x from here on. //读取请求的数据 c.r = &connReader{r: c.rwc} c.bufr = newBufioReader(c.r) c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10) ctx, cancelCtx := context.WithCancel(ctx) defer cancelCtx() for { w, err := c.readRequest(ctx) ...... serverHandler{c.server}.ServeHTTP(w, w.req) ... }}
The request went down by seven, and finally entered:
serverHandler{c.server}.ServeHTTP(w, w.req)
and called the serverhandler.servehttp inside it. Decisive point open this function, enlightened, originally was called the topmost:
http.DefaultServeMux.Handle
Do not believe to look here:
type serverHandler struct { srv *Server}func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { //sh.srv.Handler =server.handler handler := sh.srv.Handler if handler == nil { //我们最初传的参数就是 nil handler = DefaultServeMux } if req.RequestURI == "*" && req.Method == "OPTIONS" { handler = globalOptionsHandler{} } handler.ServeHTTP(rw, req)}
So, the final deal is that the function is the servemux.servehttpin the route, and last night we've analyzed what servemux.servehttp is doing with the function we passed in. After the server opens a request comes in, the first call is Server.servehttp (rw responsewriter, req *request).
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { ..... h, _ := mux.Handler(r) h.ServeHTTP(w, r)}
The above function goes through Daoteng and finally goes to the Servemux#handler function:
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) { mux.mu.RLock() defer mux.mu.RUnlock() // Host-specific pattern takes precedence over generic ones if mux.hosts { h, pattern = mux.match(host + path) } if h == nil { h, pattern = mux.match(path) } if h == nil { h, pattern = NotFoundHandler(), "" } return}
In this method, the URL is matched. The handle of the corresponding URL is returned on the match, otherwise it is called Notfoundhandler. Then call MuxEntry.h, which is the logical function of our custom processing.
Such a complete request HTTP request in the Golang inside of the flow process is very clear, is not it?
Attention Program Ape Public account: