GOLANG 中 HTTP 包默认路由匹配规则

本贴最后更新于 2101 天前,其中的信息可能已经时移俗易

还是在继续学习 Go 的路上,曾经在使用 PHP 的时候吃过过度依赖框架的亏。现在学习 Go 的时候决定先打好基础,从标准库学起走。

源码分析

我们知道最简单的建立 http 服务器代码基本上都是这样的:

http.HandleFunc('/', func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello world") }) http.ListenAndServe(":8080", nil)

这样就成功的建立了一个监听 8080 端口的 http 服务器,当访问的时候输出 Hello world

我们顺藤摸瓜来看看 HandleFunc 做了些什么事:

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

这里继续通过调用 DefaultServeMuxHandleFunc 方法注册路由,这个 DefaultServeMux 又是何方圣神:

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 } // NewServeMux allocates and returns a new ServeMux. func NewServeMux() *ServeMux { return new(ServeMux) } // DefaultServeMux is the default ServeMux used by Serve. var DefaultServeMux = &defaultServeMux var defaultServeMux ServeMux

DefaultServeMuxnet/http 包提供的一个默认的 ServeMux 类型,ServeMux 实现了 Handler 接口。

追根究底,发现 http 服务器收到一条请求后通过 go c.serve(ctx) 开启 goroutine 处理这个请求,在这个过程中调用了 Handler 接口函数 ServeHTTP 来做进一步的处理(比如匹配方法、链接等等)。

所以,我们就可以理解 ServeMux 就是 net/http 一个内置的路由功能。

继续回到 HandleFunc 来:

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { mux.Handle(pattern, HandlerFunc(handler)) }

ServeMuxHandleFunc 方法将我们传入的路由具体实现函数转换成 HandlerFunc 类型并通过 Handle 注册到路由。这个 HandlerFunc 类型也实现了 Handler 接口:

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

最后到了 Handle 这个方法, Handle 方法通过将 pattern 路径以及实现了 Handler 接口的方法一一对应的保存到 ServeMuxmap[string]muxEntry 中,方便后续请求的时候调用。因此,也可以通过 Handle 直接传入一个实现了 Handler 接口的方法注册路由。

至此,net/http 包中默认路由的注册过程基本上已经走完。

至于请求的时候路由调用,记住通过 ServeHTTP 查找 map 中对应路径并调用相关方法就行了。

自制路由

通过以上的分析,我们可以依样画葫芦,实现自己的路由功能。

package route import ( "net/http" "strings" ) // 返回一个Router实例 func NewRouter() *Router { return new(Router) } // 路由结构体,包含一个记录方法、路径的map type Router struct { Route map[string]map[string]http.HandlerFunc } // 实现Handler接口,匹配方法以及路径 func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { if h, ok := r.Route[req.Method][req.URL.String()]; ok { h(w, req) } } // 根据方法、路径将方法注册到路由 func (r *Router) HandleFunc(method, path string, f http.HandlerFunc) { method = strings.ToUpper(method) if r.Route == nil { r.Route = make(map[string]map[string]http.HandlerFunc) } if r.Route[method] == nil { r.Route[method] = make(map[string]http.HandlerFunc) } r.Route[method][path] = f }

使用:

r := route.NewRouter() r.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello Get!") }) r.HandleFunc("POST", "/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "hello POST!") }) http.ListenAndServe(":8080", r)

这个例子只是依样画葫芦的简单功能实现。

一个完整的路由框架应该包含更复杂的匹配、错误检测等等功能,大家可以试着自己动手试试。

阅读源码和重复造轮子都是学习的方法。

最后,欢迎大家关注我的博客 http://targetliu.com/

  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    499 引用 • 1395 回帖 • 245 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 心情

    心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。

    59 引用 • 369 回帖
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 48 关注
  • Excel
    31 引用 • 28 回帖
  • GraphQL

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

    4 引用 • 3 回帖 • 13 关注
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    181 引用 • 400 回帖 • 1 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    7 引用 • 69 回帖 • 6 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    77 引用 • 37 回帖
  • SVN

    SVN 是 Subversion 的简称,是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统,它的设计目标就是取代 CVS。

    29 引用 • 98 回帖 • 692 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 3 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 585 回帖 • 1 关注
  • 音乐

    你听到信仰的声音了么?

    62 引用 • 512 回帖 • 1 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 248 回帖 • 1 关注
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 111 关注
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    326 引用 • 1395 回帖
  • 倾城之链
    23 引用 • 66 回帖 • 169 关注
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    54 引用 • 37 回帖 • 3 关注
  • OneNote
    1 引用 • 3 回帖
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 51 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    947 引用 • 1460 回帖 • 1 关注
  • 印象笔记
    3 引用 • 16 回帖 • 1 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    134 引用 • 1127 回帖 • 110 关注
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 463 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    91 引用 • 122 回帖 • 623 关注
  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    172 引用 • 534 回帖