go的http详解
2017-04-29 19:17
302 查看
Go提供了一个完善的net/http包用于搭建web服务器,同时http能很简单的对web的路由进行设置和操作。
http包建立的简单的web服务器,路由器的配置,请求的监听和处理。
内部默认的路由器结构:
http包中有两个注册内部路由规则的方法:Handle函数和HandleFunc函数,这两个函数底层都
是调用了DefaultServerMux对象的Handle函数。
外部自定义路由就是定义一个struct实现ServeHTTP函数,在ServeHTTP中进行路由转发。
请求处理。函数的底层实现主要是初始化一个server对象,然后调用net.Listen("tcp", addr)利用tcp进行端
口监听,然后通过server对象的Serve函数进行http请求的接收和处理。
server对象的Serve函数的实现
http包建立的简单的web服务器,路由器的配置,请求的监听和处理。
package main import ( "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 ServeMux type ServeMux struct { mu sync.RWMutex//同步锁,用于涉及并发的请求处理 m map[string]muxEntry//路由规则,一个string对应一个muxEntry hosts bool // whether any patterns contain hostnames } type muxEntry struct { explicit bool//是否精确匹配 h Handler//路由对应的handle pattern 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 := pattern if 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 main import ( "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 failure for { 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 = 0 c := srv.newConn(rw)//对于每个请求实例化一个conn对象 c.setState(c.rwc, StateNew) // before Serve can return go 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获取对应的handler h.ServeHTTP(w, r)//执行handler的ServerHTTP函数处理请求 }
相关文章推荐
- HTTP引流神器Goreplay详解【精译】
- Go的http包详解
- Go的http包详解
- javascript中Http部分方法详解
- 【META http-equiv="Content-Type" Content="text/html; Charset=*】意义详解
- HTTP_HOST 和 SERVER_NAME 的区别详解
- ASP 中使用 HTTP 协议发送参数详解
- AJAX核心对象-- XMLHttpRequest 对象使用详解 (二)
- 详解Windows 2000/XP Class/Port/Miniport驱动模型(http://webcrazy.yeah.net)
- ajax xmlhttp对象详解
- php的fckeditor配置详解zz [出自: http://www.phpx.com]
- http://www.moj.go.jp/ONLINE/IMMIGRATION/16-3.html
- 对话框showModelessDialog()使用详解http://www.weste.net/html/200404/20040414QBI152055.html
- 网络编程基础:对HTTP协议的头信息详解
- HTTP 协议基础,http头信息详解
- http 头信息详解
- session详解-[http://blog.csdn.net/dazern/]
- GNU Go(http://www.gnu.org/software/gnugo/gnugo.html)
- XMLHttpRequest对象详解
- HTTP 协议基础,http头信息详解(转)