studygolang源码阅读小结 <四>

whispermemory · 2013-04-21 13:13:40 · 4721 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2013-04-21 13:13:40 的主题,其中的信息可能已经有所发展或是发生改变。

##http与 router##

先看http 提供的强大简洁服务器端的功能

  • HTTP响应模块

    func ListenAndServe(addr string, handler Handler) error

这个方法就处理了所有的http请求。第二个参数如下

type Handler interface {
      ServeHTTP(ResponseWriter, *Request)
}

也就是实现了该接口的结构,均能够对http请求作出相应。看这个方法的参数大致就能猜出,这个方法是让使用者自己往RewponseWriter中写http header 以及http data。

type ResponseWriter interface {
       Header() Header    
       Write([]byte) (int, error)
       WriteHeader(int)
   }

当第二个参数为空的时候,默认由系统的对象http.DefaultServeMux进行处理,看结构体

type ServeMux struct {
    // contains filtered or unexported fields
}

这个对象会对Listen到的http请求进行路由。让不同的Handler进行处理。因此在Listen之前需要对ServeMux注册Handler。调用下面方法即可

func Handle(pattern string, handler Handler)
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

第一个方法的第二个参数是一个Handle类型接口,第二个方法是直接提供了一个Handle接口需要的接口方法。总之需要一个实现serveHTTP的结构体。而这个结构体则是studygolang很关键的一个模块。即router

  • Router

Router这个结构体在studygolang中最重要的作用就是handler的路由,看ServeHttp提供的路由功能代码:

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    // Clean path to canonical form and redirect.
    if p := cleanPath(req.URL.Path); p != req.URL.Path {
        w.Header().Set("Location", p)
        w.WriteHeader(http.StatusMovedPermanently)
        return
    }
    var match RouteMatch
    var handler http.Handler
    if r.Match(req, &match) {
        handler = match.Handler
        setVars(req, match.Vars)
        setCurrentRoute(req, match.Route)
    }
    if handler == nil {
        if r.NotFoundHandler == nil {
            r.NotFoundHandler = http.NotFoundHandler()
        }
        handler = r.NotFoundHandler
    }
    defer context.Clear(req)
    handler.ServeHTTP(w, req)
}

在Router内嵌Route指针数组,通过Route来跟request进行匹配。而Route内部则存储http.Handler。如果匹配成功则,使用该Route内的Handler对请求进行响应。

type Route struct {
    // Parent where the route was registered (a Router).
    parent parentRoute
    // Request handler for the route.
    handler http.Handler
    // List of matchers.
    matchers []matcher
    // Manager for the variables from host and path.
    regexp *routeRegexpGroup
    // If true, when the path pattern is "/path/", accessing "/path" will
    // redirect to the former and vice versa.
    strictSlash bool
    // If true, this route never matches: it is only used to build URLs.
    buildOnly bool
    // The name used to build URLs.
    name string
    // Error resulted from building a route.
    err error

    // 过滤器链
    FilterChain *FilterChain
}

通过该结构体的源码可以明白Route跟Path之间的关系是一一对应的,在每一个Route里面存储有一个Path。Route跟handle也是一一对应的,但是一个Route里面是可以有多个Filter的。首先是request 跟 Route之间的匹配。只要拿到request的URI就可以获取相匹配的Path。其次是Filter的调用与Handler的调用关系,就是Filter模块。


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4721 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传