hello world
package mainimport ("log""net/http")func main() {http.HandleFunc("/v1/hello", func(writer http.ResponseWriter, request *http.Request) {writer.Write([]byte("hello http\n"))})log.Fatal(http.ListenAndServe(":8090",nil))}
启动当前服务
curl -X GET 'http://localhost:8090/v1/hello'hello http
ServeHTTP
type BaseHander struct {}func (hander *BaseHander)ServeHTTP(resp http.ResponseWriter,req *http.Request){fmt.Println("url path=>",req.URL.Path)fmt.Println("url param a =>",req.URL.Query().Get("a"))resp.Write([]byte("hello world"))}func main() {http.ListenAndServe(":8080",&BaseHander{});}
muxHandler 路由
type ServeMux struct {mu sync.RWMutexm map[string]muxEntryes []muxEntry // slice of entries sorted from longest to shortest.hosts bool // whether any patterns contain hostnames}type muxEntry struct {h Handlerpattern string}type Handler interface {ServeHTTP(ResponseWriter, *Request) // 路由实现器}
Handler是一个接口,但是前一小节中的sayhelloName函数并没有实现ServeHTTP这个接口,为什么能添加呢?原来在http包里面还定义了一个类型HandlerFunc,我们定义的函数sayhelloName就是这个HandlerFunc调用之后的结果,这个类型默认就实现了ServeHTTP这个接口,即我们调用了HandlerFunc(f),强制类型转换f成为HandlerFunc类型,这样f就拥有了ServeHTTP方法。
package muximport ("net/http")type muxHandler struct {handlers map[string]http.HandlerhandleFuncs map[string]func(resp http.ResponseWriter, req *http.Request)}func NewMuxHandler() *muxHandler {return &muxHandler{make(map[string]http.Handler),make(map[string]func(resp http.ResponseWriter, req *http.Request)),}}func (handler *muxHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {urlPath := req.URL.Pathif hl, ok := handler.handlers[urlPath]; ok {hl.ServeHTTP(resp, req)return}if fn, ok := handler.handleFuncs[urlPath]; ok {fn(resp, req)return}http.NotFound(resp, req)}func (hander *muxHandler) Handle(pattern string, hl http.Handler) {hander.handlers[pattern] = hl}func (handler *muxHandler) HandleFunc(pattern string, fn func(resp http.ResponseWriter, req *http.Request)) {handler.handleFuncs[pattern] = fn}
var (port string)func main() {flag.StringVar(&port, "port", ":8080", "port to listen")flag.Parse()router :=mux.NewMuxHandler()router.Handle("/hello/golang/", &BaseHander{})router.HandleFunc("/hello/world", func(resp http.ResponseWriter, req *http.Request) {resp.Write([]byte("hello world"))})http.ListenAndServe(port, router)}
go web的请求流程

go10.1的源码
func (srv *Server) Serve(l net.Listener) error {defer l.Close()if fn := testHookServerServe; fn != nil {fn(srv, l)}var tempDelay time.Duration // how long to sleep on accept failureif err := srv.setupHTTP2_Serve(); err != nil {return err}srv.trackListener(l, true)defer srv.trackListener(l, false)baseCtx := context.Background() // base is always background, per Issue 16220ctx := context.WithValue(baseCtx, ServerContextKey, srv)for {rw, e := l.Accept()if e != nil {select {case <-srv.getDoneChan():return ErrServerCloseddefault:}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 := srv.newConn(rw)c.setState(c.rwc, StateNew) // before Serve can returngo c.serve(ctx)}}
go c.serve()这里我们可以看到客户端的每次请求都会创建一个Conn,这个Conn里面保存了该次请求的信息,然后再传递到对应的handler,该handler中便可以读取到相应的header信息,这样保证了每个请求的独立性。
参考
https://github.com/ma6174/blog/issues/11
https://www.cnblogs.com/itbsl/p/12175645.html
