圖片模仿build web application with golang,學習畫圖技巧。git
經過學習發現go寫http server主要有如下兩種方式,本文是分析beego中的httpServer和graceServer的基礎前提。經過分析源碼,和unix中開發server中的方式(socket,bind,listen,accetp)串連起來,而不單單是go給咱們提供好的幾個api。
package main import ( "log" "net/http" ) type sayHandler struct { } func (h *sayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello")) } func main() { log.Fatal(http.ListenAndServe(":8080", new(sayHandler))) }
code-1-1github
// Package main provides ... package main import ( "log" "net/http" ) func say(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello world")) } func main() { http.HandleFunc("/hello", say) log.Fatal(http.ListenAndServe(":8080", nil)) }
code-1-2golang
先分析code-1-1中的代碼,從ListenAndServe開始web
func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe() }
code-1-3
看下Serverapi
type Server struct { Addr string Handler Handler ... }
code-1-4
繼續看下Handlerapp
type Handler interface { ServeHTTP(ResponseWriter, *Request) }
code-1-5
這裏咱們看到ListenAndServe第二個參數只要實現code-1-5中的接口就能夠了。
咱們回到code-1-3中繼續分析。socket
func (srv *Server) ListenAndServe() error { .... ln, err := net.Listen("tcp", addr) .... return srv.Serve(ln) }
code-1-6
這裏調用了Listen,繼續下tcp
func (srv *Server) Serve(l net.Listener) error { .... for { rw, e := l.Accept() ... c := srv.newConn(rw) c.setState(c.rwc, StateNew) go c.serve(ctx) } }
code-1-7
這裏調用了Accetp,獲得了socket鏈接。
看一下newConn,這個主要是封裝下,能夠讀取server的方法。go c.serve(ctx)
能夠每一個鏈接一個協程處理。ide
func (srv *Server) newConn(rwc net.Conn) *conn { c := &conn{ server: srv, rwc: rwc, } ... return c }
code-1-8學習
// Serve a new connection. func (c *conn) serve(ctx context.Context) { ... for { w, err := c.readRequest(ctx) ... serverHandler{c.server}.ServeHTTP(w, w.req) ... }
code-1-9
serverHandler{c.server}.ServeHTTP(w, w.req)
會調用ServeHTTP方法。若是調用時傳了Handler,則調用Handler的Serve。到如今咱們回答了code-1-1中的問題了。
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) }
code-1-10
code-1-2中的代碼使用的是DefaultServeMux,咱們下篇文章分析。
http-servers
function handler
build-web-application-with-golang