图片模仿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