go的http详解

来源:互联网 发布:java交换函数 编辑:程序博客网 时间:2024/04/27 22:56

       Go提供了一个完善的net/http包用于搭建web服务器,同时http能很简单的对web的路由进行设置和操作。

      http包建立的简单的web服务器,路由器的配置,请求的监听和处理。

package mainimport ("fmt""net/http""log")type sayHello struct{}func (s *sayHello) ServeHTTP(w http.ResponseWriter, r *http.Request){fmt.Println("sayhello")fmt.Fprintf(w,"sayhello")}func hello(w http.ResponseWriter, r *http.Request){fmt.Println("hello")fmt.Fprintf(w,"hello")}func main(){t:=&sayHello{}http.HandleFunc("/",hello)http.Handle("/index",t)http.ListenAndServe(":8080",nil)}

路由器的配置

      http服务端程序主要有内部默认路由器和外部自定义路由器。
      内部默认的路由器结构:  

var DefaultServeMux = &defaultServeMux//内部默认路由器var defaultServeMux ServeMuxtype ServeMux struct {mu    sync.RWMutex//同步锁,用于涉及并发的请求处理m     map[string]muxEntry//路由规则,一个string对应一个muxEntryhosts bool // whether any patterns contain hostnames}type muxEntry struct {explicit bool//是否精确匹配h        Handler//路由对应的handlepattern  string//匹配字符串}type Handler interface {ServeHTTP(ResponseWriter, *Request)}

       http包中有两个注册内部路由规则的方法:Handle函数和HandleFunc函数,这两个函数底层都

是调用了DefaultServerMux对象的Handle函数。

type HandlerFunc func(ResponseWriter, *Request)// HandlerFunc实现ServeHTTP方法,得以适配handler接口func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {f(w, r)}//通过传入实现ServeHTTP方法的类型func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }//通过传入func(ResponseWriter, *Request)类型的方法,注册路由func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {DefaultServeMux.HandleFunc(pattern, handler)}func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {mux.Handle(pattern, HandlerFunc(handler))}//底层的路由存储,以string-muxEntry的形式存到DefaultServeMux的m中func (mux *ServeMux) Handle(pattern string, handler Handler) {mux.mu.Lock()defer mux.mu.Unlock()if mux.m == nil {mux.m = make(map[string]muxEntry)}mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}if pattern[0] != '/' {mux.hosts = true}n := len(pattern)if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {path := patternif pattern[0] != '/' {path = pattern[strings.Index(pattern, "/"):]}url := &url.URL{Path: path}mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(url.String(), StatusMovedPermanently), pattern: pattern}}}
       外部自定义路由器

      外部自定义路由就是定义一个struct实现ServeHTTP函数,在ServeHTTP中进行路由转发。

package mainimport ("fmt""net/http")type MyMux struct {}func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {if r.URL.Path == "/" {hello(w, r)return}http.NotFound(w, r)return}func hello(w http.ResponseWriter, r *http.Request){fmt.Println("hello")fmt.Fprintf(w,"hello")}func main() {mux := &MyMux{}http.ListenAndServe(":9090", mux)}

请求监听和处理

       从web服务端处理程序可以看到ListenAndServe函数进行了端口的监听,接收请求,分配handle进行

请求处理。函数的底层实现主要是初始化一个server对象,然后调用net.Listen("tcp", addr)利用tcp进行端

口监听,然后通过server对象的Serve函数进行http请求的接收和处理。

func ListenAndServe(addr string, handler Handler) error {server := &Server{Addr: addr, Handler: handler}return server.ListenAndServe()}func (srv *Server) ListenAndServe() error {addr := srv.Addr……ln, err := net.Listen("tcp", addr)……return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})}  

     server对象的Serve函数的实现

func (srv *Server) Serve(l net.Listener) error {defer l.Close()var tempDelay time.Duration // 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}time.Sleep(tempDelay)continue}return e}tempDelay = 0c := srv.newConn(rw)//对于每个请求实例化一个conn对象c.setState(c.rwc, StateNew) // before Serve can returngo c.serve(ctx)//开启一个goroutine接收数据并处理}}func (c *conn) serve(ctx context.Context) {……for {//读取请求数据w, err := c.readRequest(ctx)……serverHandler{c.server}.ServeHTTP(w, w.req)……}}func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {handler := sh.srv.Handler//ListenAndServe传入的自定义路由器if handler == nil {//没有传入自定义路由器handler = DefaultServeMux//http包的默认路由器}handler.ServeHTTP(rw, req)}func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {……h, _ := mux.Handler(r)//根据url获取对应的handlerh.ServeHTTP(w, r)//执行handler的ServerHTTP函数处理请求}



0 0
原创粉丝点击