Golang http Handlefunc

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Golang HTTP's handle module (commonly referred to as the Hook module), this embedded function is easily implemented by anonymous functions in high-level languages handle

In general, we use Golang HTTP handlefunc to handle the server side of HTTP as appropriate

/*********************************************/http. Handlefunc ("/", xxx_fun) Err: = http. Listenandserve (": 8080", nil) if err! = Nil {log. Fatal ("Listenandserve:", err)}/*********************************************/

Let's go deep into the source code and take a closer look at http. The realization of Handlefunc

Func handlefunc (Pattern string, handler func (responsewriter, *request))  { Defaultservemux.handlefunc (Pattern, handler)}// newservemux allocates and returns  a new servemux.var defaultservemux = newservemux () Func NewServeMux ()   *servemux { return &servemux{m: make (map[string]muxentry)} }type ServeMux  struct {mu    sync. rwmutex                    //A read-write lock m     map[string]muxentry             //Mapping of a path (patterns) maphosts bool                            // whether any patterns contain hostnames}

Take a look at the concrete implementation of Listenandserve

Func listenandserve (Addr string, handler handler)  error {server :=  &server{addr: addr, handler: handler}return server. Listenandserve ()}func  (srv *server)  listenandserve ()  error {addr := srv. addrif addr ==  ""  {addr =  ": http"}ln, err := net. Listen ("TCP",  addr) if err != nil {return err}return srv. Serve (Tcpkeepalivelistener{ln. ( *net. TcpListener)})}// serve accepts incoming connections on the listener l ,  creating a// new service goroutine for each.  the service  goroutines read requests and// then call srv. handler to reply to them.func  (Srv *server)  serve (l net. Listener)  error {defer l.close () var tempdelay time. Duration //&nBsp;how long to sleep on accept failurefor {rw, e := l. Accept () if e != nil {if ne, ok := e. (NET. Error);  ok && ne. Temporary ()  {if tempdelay == 0 {tempdelay = 5 * time. Millisecond} else {tempdelay *= 2}if max := 1 * time. SECOND; TEMPDELAY > MAX {TEMPDELAY = MAX}SRV.LOGF ("http: Accept  Error: %v; retrying in %v ",  e, tempdelay) time. Sleep (Tempdelay) continue}return e}tempdelay = 0c, err := srv.newconn (rw) if  Err != nil {continue}c.setstate (c.rwc, statenew)  // before serve can  returngo c.serve ()  //It seems that this c.serve is the processing entrance}}

It appears that this c.serve is a processing portal

 Serve a new connection.func  (C *conn)  serve ()  {origconn :=  c.rwc // copy it before it ' s set nil on close or  Hijackdefer func ()  {if err := recover (); err != nil {const  Size = 64 << 10buf := make ([]byte, size) buf = buf[:runtime. Stack (Buf, false)]c.server.logf ("http: panic serving %v: %v\n%s",  c.remoteAddr, &NBSP;ERR,&NBSP;BUF)}if !c.hijacked ()  {c.close () c.setstate (origconn, stateclosed)}} () if  TLSCONN,&NBSP;OK&NBSP;:=&NBSP;C.RWC. (*tls. Conn);  ok {if d := c.server.readtimeout; d != 0 { C.rwc.setreaddeadline (time. Now (). ADD (d))}if d := c.server.writetimeout; d != 0 {c.rwc.setwritedeadline (time. Now (). ADD (d))}if err := tlsconn.handshake ();  err ! =&NBSP;NIL&NBSP;{C.SERVER.LOGF ("Http: tls handshake error from %s: %v",  C.rwc.remoteaddr (),  err) return}c.tlsstate = new (TLS. ConnectionState) *c.tlsstate = tlsconn.connectionstate () if proto :=  C.TLSSTATE.NEGOTIATEDPROTOCOL;&NBSP;VALIDNPN (proto)  {if fn := c.server.tlsnextproto[proto] ; &NBSP;FN&NBSP;!=&NBSP;NIL&NBSP;{H&NBSP;:=&NBSP;INITNPNREQUEST{TLSCONN,&NBSP;SERVERHANDLER{C.SERVER}}FN ( C.SERVER,&NBSP;TLSCONN,&NBSP;H)}return}}for {w, err := c.readrequest () if c.lr.N  != c.server.initiallimitedreadersize ()  {// if we read any bytes off  the wire, we ' Re active.c.setstate (c.rwc, stateactive)}if err != nil  {if err == errTooLarge {// Their HTTP client may or  May not be// able to read this if we ' re// responding to them and hanging up// while they ' re still  Writing their// request.  undefined behavior.io.writestring (c.rwc,  "HTTP/1.1  413 request entity too large\r\n\r\n ") c.closewriteandwait () break} else if  err == io. Eof {break // don ' T reply} else if neterr, ok := err. (NET. Error);  ok && neterr. Timeout ()  {break // don ' T reply}io. WriteString (c.rwc,  "http/1.1 400 bad request\r\n\r\n") break}// expect 100  Continue supportreq := w.reqif req.expectscontinue ()  {if req. Protoatleast (1, 1)  && req. Contentlength != 0 {// wrap the body reader with one that  replies on the connectionreq. Body = &expectcontinuereaDer{readcloser: req. Body, resp: w}}req. Header.del ("Expect")} else if req. Header.get ("Expect")  !=  ""  {w.sendexpectationfailed () Break}// http cannot have  multiple simultaneous active requests. [*]// until the server replies to this request, it can ' t  read another,// so we might as well run the handler in  This goroutine.// [*] not strictly true: http pipelining.  we  could let them all process// in parallel even if their  responses need to be serialized.serverhandler{c.server}. Servehttp (w, w.req)  //This is the entrance if c.hijacked ()  {return}w.finishrequest () if  W.closeafterreply {if w.requestbodylimithit {c.closewriteandwait ()}break}c.setState (C.RWC,  stateidle)}}

The

Handler processing entry is Serverhandler{c.server}. Serverhttp (W,w.req), final to Handlefunc execution

func  (Mux *servemux)  handler (r *request)   (h handler, pattern string)  {if r.Method !=  "CONNECT"  {if p := cleanpath (R.url. Path);  p != r.url. Path {_, pattern = mux.handler (r.host, p)  //Next process Url := *r.urlurl.path  = preturn redirecthandler (URL. String (),  statusmovedpermanently),  pattern}}return mux.handler (R.host, r.url. Path)  //Next process}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 onesif mux.hosts {h, pattern  = mux.match (Host + path)}if h == nil {h, pattern =  Mux.match (PATH)}if h == nil {h, pattern = notfoundhaNdler (),  ""  //returns the default anonymous function if the handler corresponding anonymous function is empty}return}// 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)  //next deals with H. Servehttp (w, r)  //next processes}//the next action func  (MUX&NBSP;*SERVEMUX)  handlefunc (pattern  String, handler func (responsewriter, *request))  {mux. Handle (Pattern, handlerfunc (handler))}func  (mux *seRvemux)  handle (pattern string, handler handler)  {  //processing patternmux.mu.Lock () Defer mux.mu.unlock () if pattern ==  ""  {panic ("http: invalid pattern "  + pattern)}if handler == nil {panic ("Http: nil handler")}if  Mux.m[pattern].explicit {panic ("http: multiple registrations for "  +  pattern)}mux.m[pattern] = muxentry{explicit: true, h: handler, pattern:  pattern} //set Servemux's mapif pattern[0] !=  '/'  {mux.hosts = true}//  helpful behavior:// if pattern is /tree/, insert an implicit  permanent redirect for /tree.// it can be overridden by an  Explicit registration.n := len (pattern) if n > 0 && pattern[ n-1] ==  '/'  && !mux.m[pattern[0:n-1]].explicit {// If pattern contains a host  name, strip it and use remaining// path for redirect.path :=  patternif pattern[0] !=  '/'  {// in pattern, at least the  last character is a  '/',  so// strings. Index can ' T be -1.path = pattern[strings. Index (pattern,  "/"):]}mux.m[pattern[0:n-1]] = muxentry{h: redirecthandler (path,  statusmovedpermanently),  pattern: pattern}}}

Finally, take a look at the operation of the corresponding map with a MUX match:

Func (Mux *servemux) match (Path string) (H Handler, pattern string) {var n = 0for k, V: = Range mux.m {if!pathmatch (K, PA TH) {//Match continue}if H = = Nil | | Len (k) > N {n = len (k) h = V.hpattern = V.pattern}}return}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.