为了账号安全,请及时绑定邮箱和手机立即绑定

http.HandleFunc 解析

标签:
JavaScript

Go语言是一个神奇的语言,尤其是函数式编程,

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

就是一个典型。这个函数就是注册默认路由。
HandleFunc 的第一个参数指的是请求路径,第二个参数是一个函数类型,表示这个请求需要处理的事情。没有处理复杂的逻辑,而是直接给DefaultServeMux处理,如源码:

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {    DefaultServeMux.HandleFunc(pattern, handler)}

DefaultServeMux 是ServeMux一个全局实例,

// DefaultServeMux is the default ServeMux used by Serve.var DefaultServeMux = &defaultServeMuxvar defaultServeMux ServeMux

这个实例在被申明的时候初始化了,只要使用了DefaultServeMux这个变量,其实就是同一个指针而已,也就是独一份。
DefaultServeMux.HandleFunc(pattern, handler) 函数其实也没有做什么,直接调用路由注册:

// HandleFunc registers the handler function for the given pattern.func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {    mux.Handle(pattern, HandlerFunc(handler))}

把自定义处理业务的函数进行路由注册,HandlerFunc(handler) 这个处理其实是类型转化,把函数handler  func 类型转化成HandlerFunc类型,是一个强制转化,只要函数的参数类型一致,即可转化。我们来看一个HandlerFunc是如何定义的:

type HandlerFunc func(ResponseWriter, *Request)// ServeHTTP calls f(w, r).func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {    f(w, r)}

从type可以看出 HandlerFunc 就是一个自定义类型,被定义成

func(ResponseWriter, *Request)

函数。所以只要符合此标准的函数,都可以转化成HandlerFunc,而这个函数实现了接口:

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

这个接口就是路由中,匹配的处理方法。

根据go对接口的定义,只有实现了接口的所有方法,就实现了这个接口。

我们来看是如何注册路由的,需要理解如下两个结构

  • ServeMux 多路路由器

  • muxEntry  具体路由

type ServeMux struct {    mu    sync.RWMutex //锁    m     map[string]muxEntry //路由集合    hosts bool // whether any patterns contain hostnames}type muxEntry struct {    explicit bool //是否已经存在    h        Handler  //路由处理逻辑 是一个接口实例  在每次匹配的时候,调用此接口的方法    pattern  string//请求路径}

处逻辑源码如下:

// Handle 根据给定的请求路劲进行注册路由// 如果Handle已经存在,就直接报错func (mux *ServeMux) Handle(pattern string, handler Handler) { //进行加锁,高并发处理    mux.mu.Lock()    //释放锁    defer mux.mu.Unlock() //请求路径为空,直接报错    if pattern == "" {        panic("http: invalid pattern " + pattern)    }    //Handle不存在,直接报错    if handler == nil {        panic("http: nil handler")    }    //如果Handle已经存在,就直接报错    if mux.m[pattern].explicit {        panic("http: multiple registrations for " + pattern)    }//路由表不存在,创建一个,这个路由表是一个映射MAP//key 就是请求路径  value是muxEntry 包含具体路由信息    if mux.m == nil {        mux.m = make(map[string]muxEntry)    }    mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}//如果首字母不是‘/’ 包含hostName    if pattern[0] != '/' {        mux.hosts = true    }    // Helpful behavior:    // If pattern is /tree/, insert an implicit permanent redirect for /tree.    // It can be overridden by an explicit registration.    n := len(pattern)    //如何是像/tree/ 请求注册路由,而且/tree 还没有注册过    if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {        // If pattern contains a host name, strip it and use remaining        // path for redirect.        path := pattern //保存原始路径        if pattern[0] != '/' { //如果首字母不是 ‘/’            // In pattern, at least the last character is a '/', so            // strings.Index can't be -1.            path = pattern[strings.Index(pattern, "/"):] //返回最近的/之后的串作为请求路径        }        //构建请求URL 直接重定向 而且注册的注册路径有/tree/  /tree        url := &url.URL{Path: path}        mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(url.String(), StatusMovedPermanently), pattern: pattern}    }}

以上是对函数

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

调用过程分析

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消