ServeMux简介

ServeMux扮演的角色是Multiplexer,它用来将将请求根据url路由给已注册的handler。如下图:

上图中为3个路径注册了handler,一个是"/",另外两个是"/hello"和"/world"。这表示访问http://hostname/hello时,multiplexer会调用上图中对应的第二个handler,当访问http://hostname/world时,multiplexer会调用上图中对应的第三个handler,当不是这两个路径时,将调用第一个绑定在"/"上的handler。

注意,go的mux路由请求时,handler绑定的路径是否带尾随"/"是不一样的。带上尾随"/",表示此路径以及此路径下的子路径,都会调用注册在此路径上的handler

例如,当请求uri为"/hello/abc"的时候,不会调用"/hello"对应的handler,而是调用"/"对应的handler。只有注册handler的路径为"/hello/"时,uri为"/hello/abc"才会调用此handler。

实际上,当注册handler的路径带上尾随斜"/"时,在发起此路径的请求时,会通过301重定向的方式自动补齐这个尾随斜线,让浏览器发起第二次请求。例如,下面是注册handler的路径:

http.Handle("/hello/", &myHandler)

发起http://hostname/hello的请求时,会自动补齐为http://hostname/hello/,然后浏览器自动发起第二次请求。

ServeMux的匹配规则

ServeMux对每次流入的http请求的URL进行模式(pattern)匹配,然后调用注册在此pattern上的handler来处理这个请求。

Pattern部分可以定义为匹配host的模式。如果pattern以"/"开头,表示匹配URL的路径部分,如果不以"/"开头,表示从host开始匹配。

匹配时选择匹配匹配度最高(长匹配优先于短匹配)。例如为"/images/"注册了handler1,"/images/thumbnails/"注册了handler2,如果请求的URL路径部分为"/images/thumbnails/",将会调用handler2处理这个请求,如果请求的URL路径部分为"/images/foo/",将调用handler1处理。

注意,注册在"/"上的pattern会在其它模式匹配不上时被选中,因为所有请求都可以匹配这个pattern,只不过能匹配到的长度最短。

如果pattern带上了尾随斜线"/",ServeMux将会对请求不带尾随斜线的URL进行301重定向。例如,在"/images/"模式上注册了一个handler,当请求的URL路径为"/images"时,将自动重定向为"/images/"。除非再单独为"/images"模式注册一个handler。

如果为"/images"注册了handler,当请求URL路径为"/images/"时,将无法匹配该模式。

ServeMux详细解释

看看net/http/server.go文件中ServeMux的结构:

type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
hosts bool // whether any patterns contain hostnames
} type muxEntry struct {
h Handler
pattern string
}

结构看上去很简单。一个字段mu是RWMutex,m是注册handler和pattern的,hosts用于判断pattern是否包含了host的匹配。看看Handle()函数的定义会更清晰:

func (mux *ServeMux) Handle(pattern string, handler Handler) {
mux.mu.Lock()
defer mux.mu.Unlock() if pattern == "" {
panic("http: invalid pattern")
}
if handler == nil {
panic("http: nil handler")
}
if _, exist := mux.m[pattern]; exist {
panic("http: multiple registrations for " + pattern)
} if mux.m == nil {
mux.m = make(map[string]muxEntry)
}
mux.m[pattern] = muxEntry{h: handler, pattern: pattern} if pattern[0] != '/' {
mux.hosts = true
}
} // HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
mux.Handle(pattern, HandlerFunc(handler))
}

pattern为空或者handler为空时,都会panic。此外,想要定义重复的pattern,也会panic。如果pattern的第一个字符不是"/",则表示这个pattern是从主机名开始匹配的。

唯一需要注意的是,每个Handle()都会对ServeMux实例加上写锁。

以常用的DefaultServeMux为例,它是ServeMux的一个实例。当使用DefualtServeMux时,每调用一次Handle()或HandleFunc(),都意味着向这个DefaultServeMux的结构中的m字段添加pattern和对应的handler。由于加了写锁,如果使用多个goroutine同时启动多个web服务,在同一时刻将只能有一个goroutine启动的web服务能设置DefaultServeMux。当然,一般情况下不会使用goroutine的方式同时启动多个web服务。

第三方ServeMux

自带的默认的DefaultServeMux其实功能限制很大。比如请求的URL路径为"/images/123.png",想要匹配这个确实容易,但是想要取出其中的"123.png"字符串,DefaultServeMux就没法实现。

有一个非常强大的Gorilla工具包(www.gorillatoolkit.org),它有好几个功能,其中一个功能是提供multiplexer。

Go Web:自带的ServeMux multiplexer的更多相关文章

  1. 【WEB】带边框的网页页面实现

    前言 这是编程入学者尝试各种技术的备忘记录和自我激励,内容非常简单而单纯. 正文 成品 样式参考    http://tenhou.net/ 上边框 http://tenhou.net/img/f0t ...

  2. Go语言系列文章

    这个系列写的不是很好,未来重构. Go基础系列 Go基础 Go基础 1.Go简介 2.Go数据结构struct 3.构建Go程序 4.import导包和初始化阶段 5.array 6.Slice详解 ...

  3. Gulp实现web服务器

    Gulp实现web服务器 阅读目录 一:gulp实现web服务器配置: 二:添加实时刷新(livereload)支持 回到顶部 一:gulp实现web服务器配置: 对于前端开发而言,需要在本地搭建一个 ...

  4. 代码实现PHP web服务器下绝对路径到Web网址的转换

    代码实现PHP web服务器下绝对路径到Web网址的转换 代码中用到几个系统变量或常量: 1. 路径中各目录分隔字符 DIRECTORY_SEPARATOR(常量),Windows下DIRECTORY ...

  5. 整理六百篇web前端知识混总

    9个有用的和免费的工具来支持动态网页开发 8个基本的引导工具的网页设计师 11款CSS3动画工具的开发 2016年某前端群题目答案参考 9最好的JavaScript压缩工具 创建响应式布局的10款优秀 ...

  6. [Web安全] XXE漏洞攻防学习(中)

    0x00.XXE漏洞攻击实例 攻击思路: 1. 引用外部实体远程文件读取 2. Blind XXE 3. Dos 0x01.外部实体引用,有回显 实验操作平台:bWAPP平台上的XXE题目 题目: 进 ...

  7. Progressive Web App

    下一代 Web 应用? 近年来,Web 应用在整个软件与互联网行业承载的责任越来越重,软件复杂度和维护成本越来越高,Web 技术,尤其是 Web 客户端技术,迎来了爆发式的发展. 包括但不限于基于 N ...

  8. 《Agile Web Development With Rails》读后感--rails基于web设计的best Practices

    最近看完<Agile Web Development with Rails>一书,受益匪浅.书中先是用一个简单的web应用带你进入Rails的世界,然后在你大致熟悉之后,再带你了解Rail ...

  9. java web 开发三剑客 -------电子书

    Internet,人们通常称为因特网,是当今世界上覆盖面最大和应用最广泛的网络.根据英语构词法,Internet是Inter + net,Inter-作为前缀在英语中表示“在一起,交互”,由此可知In ...

随机推荐

  1. 针对zstack虚拟机导出的问题的解决办法!

    1. nfs 首先定位image所在位置: 云主机--〉云盘操作--〉配置信息--〉更多信息--安装路径 /opt/zstack/nfsprimarystorage/prim-aab63dc6284f ...

  2. Eclipse项目里面看源码和文档

    Eclipse项目里面看源码 1.新建项目列表 2.进入struts2-core-2.3.20.jar,双击之后,看不到源码 3.右键struts2-core-2.3.20.jar,选择propert ...

  3. matplotlib&numpy画图

    import numpy as np import matplotlib.pyplot as plt x=np.linspace(0,6,100) y=np.cos(2*np.pi*x)*np.exp ...

  4. spring mvc jsonp调用示例

    服务端代码:主要是返回的时候,返回值要用callback包装一下 /** * JSONP调用 * * @param request * @return */ @RequestMapping(" ...

  5. 吴恩达机器学习笔记24-神经网络的模型表示1(Model Representation of Neural Network I)

    神经网络模型建立在很多神经元之上,每一个神经元又是一个个学习模型.这些神经元(也叫激活单元,activation unit)采纳一些特征作为输出,并且根据本身的模型提供一个输出.下图是一个以逻辑回归模 ...

  6. Numpy学习一:ndarray数组对象

    NumPy是Python的一个高性能科学计算和数据分析基础库,提供了功能强大的多维数组对象ndarray.jupyter notebook快速执行代码的快捷键:鼠标点击选中要指定的代码框,Shift ...

  7. 如何把web.xml中的context-param、Servlet、Listener和Filter定义添加到SpringBoot中

    把传统的web项目迁移到SpringBoot中,少不了web.xml中的context-param.Servlet.Filter和Listener等定义的迁移. 对于Servlet.Filter和Li ...

  8. Spark基础-scala学习(八、隐式转换与隐式参数)

    大纲 隐式转换 使用隐式转换加强现有类型 导入隐式转换函数 隐式转换的发生时机 隐式参数 隐式转换 要实现隐式转换,只要程序可见的范围内定义隐式转换函数即可.Scala会自动使用隐式转换函数.隐式转换 ...

  9. Centos 基本命令不能用恢复方法

    遇到命令都不能用,直接执行下面的语句就可以: export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/roo ...

  10. Oracle SQL优化器简介

    目录 一.Oracle的优化器 1.1 优化器简介 1.2 SQL执行过程 二.优化器优化方式 2.1 优化器的优化方式 2.2 基于规则的优化器 2.3 基于成本的优化器 三.优化器优化模式 3.1 ...