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. while read line 查找指定日期的文件夹

    #!/bin/bash dir=/root/tmp targetdir=/root/tmp/tmp filenametxt=/tmp/filename.txt commandtxt=/tmp/comm ...

  2. [转]构建高性能MySQL体系

    来源:http://www.yunweipai.com/archives/21232.html 构建高性能MySQL系统涵盖从单机.硬件.OS.文件系统.内存到MySQL 本身的配置,以及schema ...

  3. [swarthmore cs75] Compiler 4 – Diamondback

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第6次大作业. 函数声明 增加函数声明.函数调用的抽象语法:在转换成anf之前还要检查函数声明和 ...

  4. 怎么解决syntaxerror:non-utf-8 code starting with \xc4'in file

    怎么解决syntaxerror:non-utf-8 code starting with \xc4'in file   首行增加,已测试可用. # coding=gbk   程序中出现中文,运行的时候 ...

  5. python装饰器同时支持有参数和无参数的练习题

    ''' 预备知识: …… @decorator def f(*args,**kwargs): pass # 此处@decorator  等价于 f = decorator(f) @decorator2 ...

  6. 时序扩展的UML状态图的测试用例生成研究

    一.基本信息 标题:时序扩展的UML状态图的测试用例生成研究 时间:2014 出版源:西南大学 领域分类:时序扩展:UML状态图:测试用例:需求规格说明:模型 二.研究背景 问题定义:时序扩展的UML ...

  7. app -webkit-box-orient: vertical 打包后不显示

    先说明问题是什么: -webkit-box-orient: vertical 这个属性在本地运行调试是存在的,但是打包后这个属性消失了: 解决办法: 1.将-webkit-box-orient: ve ...

  8. noip第32课资料

  9. eclipse不支持sun.*包的问题处理

    在项目中使用BASE64Decoder,eclipse的编辑器莫名报错, Multiple markers at this line - Access restriction: The type BA ...

  10. Postman导出Api文档

    一.最近离职要把做搞过的接口整理成文档,查了查postman好像不支持导出文档,于是写了个工具类,供大家参考! 前提你要先把postman里的接口导出来 如图: 二.所用到的包(主要Json相关的包) ...