We know that the golang
package in the net/http
network support is very good, it will make it easier for us to build a relatively simple server, we look at a code
func sayHi(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w,"Hi")}func main() { http.HandleFunc("/sayHi", sayHi) log.Fatal(http.ListenAndServe("localhost:8080", nil))}
Here is the establishment of a relatively simple server, what does this mean? Now let's talk about it, listen to a port on our local computer, then accept the client's request, and then respond to the corresponding data of the client.
Let's look at some code.
func sayHi(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w,"Hi")}func main() { serveMux := http.DefaultServeMux serveMux.HandleFunc("/sayHi", sayHi) log.Fatal(http.ListenAndServe("localhost:8080", serveMux))}
These two code functions are the same, but in the wording of a little difference, we have to analyze Handler
these HandlerFunc
, DefaultServeMux
what is the use of.
In the first paragraph of the code, HandleFunc
we look at the source of the function.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { DefaultServeMux.HandleFunc(pattern, handler)}
In the source code, this function is called and a method is called in it.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { mux.Handle(pattern, HandlerFunc(handler))}
This method is defined on the ServeMux
structure, so what is this ServeMux
specific? Now let's not take care of it, we follow the source to look down, here called a definition ServeMux
of the structure of the Handle
method, we have to see how this method specific and what role.
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) } mux.m[pattern] = muxEntry{h: handler, pattern: pattern} if pattern[0] != '/' { mux.hosts = true }}
Here we see something that seems to have been added to it, ServeMux
as if there were, and pattern
handler
, what is the use of adding these things, so let's go back and look at the top second piece of code.
serveMux := http.DefaultServeMuxserveMux.HandleFunc("/sayHi", sayHi)
The previous large section of code is to prepare for these two lines of code, if it is written in this way, we need to put our own defined functions sayHi
into the Servemux, but Golang for we have done a default that serveMux
is DefaultServeMux
, then we need to access the url
Path /sayHi
, corresponding to the processing method in DefaultServeMux
one by one corresponds, then we have a little understanding here, this DefaultServeMux
is not to store our access path and the method to be processed a collection of it?
是的
, the stored is the pattern
corresponding handler
, where we call it 路由
.
So this corresponds to how to work, here you need to look at http.ListenAndServe("localhost:8080", serveMux)
the source code.
Let's take a look at the concrete how to achieve, here the source is longer, we choose the more important paragraphs to see
func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe()}
Here will listen to the address and incoming to be processed handler
, and then look down
go c.serve(ctx)
Here with the start goroutine
to serve each client's request, the final processing is in c.serve
this method, in this method, there is a place worth noting.
serverHandler{c.server}.ServeHTTP(w, w.req)
Here again a ServeHTTP
method is called, and then go to see what this method is dealing with.
In this method we see a code like this
if handler == nil { handler = DefaultServeMux }...handler.ServeHTTP(rw, req)
Here to see if there is no incoming handler
, then use the default DefaultServeMux
, now we understand why in the first section of the code we want to pass in one nil
, and then handler.ServeHTTP(rw, req)
, is called the implementation of the interface Handler
, so that you can decide pattern
which one to go to the corresponding handler
, see here we probably can understand this server's approximate principle is how, of course, this is a very superficial analysis, there are many deep-seated things need to study.