目录【阅读时间:约10分钟】

  • 一.概述
  • 二.对比: gorilla/mux与net/http DefaultServeMux
  • 三.简单使用
  • 四.源码简析
    • 1.NewRouter函数
    • 2.HandleFunc函数
      • 设置路由的HTTP方法
      • 设置路由的域名
      • 限制HTTP 方案
      • 设置路径前缀和子路由
    • 3.PathPrefix函数
  • 五.References

一.概述

gorilla/mux程序包,是一个强大的url路由和调度器,它具有小巧但是稳定高效的特性。

不仅可以支持正则路由,还可以按照Method、header、host等信息匹配,可以从我们设定的路由表达式中提取出参数方便上层应用,而且完全兼容http.ServerMux。

二.对比: gorilla/mux与net/http DefaultServeMux

Go 官方标准库 net/http 自带的 DefaultServeMux 底层实现,通过 DefaultServeMux 提供的路由处理器虽然简单易上手,但是存在很多不足,比如:

  • 不支持参数设定,例如 /user/:uid 这种泛类型匹配;
  • 对 REST 风格接口支持不友好,无法限制访问路由的方法;
  • 对于拥有很多路由规则的应用,编写大量路由规则非常繁琐。

为此,我们可以使用第三方库 gorilla/mux 提供的更加强大的路由处理器(mux 代表 HTTP request multiplexer,即 HTTP 请求多路复用器),和 http.ServeMux 实现原理一样,gorilla/mux 提供的路由器实现类 mux.Router 也会匹配用户请求与系统注册的路由规则,然后将用户请求转发过去。

mux.Router 主要具备以下特性:

  • 实现了 http.Handler 接口,所以和 http.ServeMux 完全兼容;
  • 可以基于 URL 主机、路径、前缀、scheme、请求头、请求参数、请求方法进行路由匹配;
  • URL 主机、路径、查询字符串支持可选的正则匹配;
  • 支持构建或反转已注册的 URL 主机,以便维护对资源的引用;
  • 支持路由嵌套(类似 Laravel 中的路由分组),以便不同路由可以共享通用条件,比如主机、路径前缀等。

三.简单使用

安装程序包:

go get -u github.com/gorilla/mux

样例①:
基于Golang的简单web服务程序开发——CloudGo
主要的相关函数为NewServer函数与initRoutes函数:

// NewServer configures and returns a Server.
func NewServer() *negroni.Negroni {formatter := render.New(render.Options{Directory:  "templates",Extensions: []string{".html"},IndentJSON: true,})n := negroni.Classic()mx := mux.NewRouter()initRoutes(mx, formatter)n.UseHandler(mx)return n
}func initRoutes(mx *mux.Router, formatter *render.Render) {webRoot := os.Getenv("WEBROOT")if len(webRoot) == 0 {if root, err := os.Getwd(); err != nil {panic("Could not retrive working directory")} else {webRoot = root//fmt.Println(root)}}mx.HandleFunc("/api/test", apiTestHandler(formatter)).Methods("GET")mx.HandleFunc("/", homeHandler(formatter)).Methods("GET")mx.HandleFunc("/user", userHandler).Methods("POST")mx.PathPrefix("/").Handler(http.FileServer(http.Dir(webRoot + "/assets/")))
}

样例②:

package mainimport ("fmt""github.com/gorilla/mux""log""net/http"
)func sayHelloWorld(w http.ResponseWriter, r *http.Request)  {w.WriteHeader(http.StatusOK)  // 设置响应状态码为 200fmt.Fprintf(w, "Hello, World!")  // 发送响应到客户端
}func main()  {r := mux.NewRouter()r.HandleFunc("/hello", sayHelloWorld)log.Fatal(http.ListenAndServe(":8080", r))
}

main 函数中的第一行显式初始化了 mux.Router 作为路由器,然后在这个路由器中注册路由规则,最后将这个路由器传入 http.ListenAndServe 方法,整个调用过程和之前并无二致,因为我们前面说了,mux.Router 也实现了 Handler 接口。

运行这段代码,在浏览器访问 http://localhost:8080/hello,即可渲染出如下结果:

Hello, World!

四.源码简析

gorilla/mux源码可分为context、mux、regex、route四个部分,在CloudGo项目开发过程中,我主要使用了NewRouter、HandleFunc和PathPrefix这三个函数。下面对这三个函数进行分析:

1.NewRouter函数

Router是一个结构体,如下:

type Router struct {// Configurable Handler to be used when no route matches.NotFoundHandler http.Handler// Configurable Handler to be used when the request method does not match the route.MethodNotAllowedHandler http.Handler// Parent route, if this is a subrouter.parent parentRoute// Routes to be matched, in order.routes []*Route// Routes by name for URL building.namedRoutes map[string]*Route// See Router.StrictSlash(). This defines the flag for new routes.strictSlash bool// See Router.SkipClean(). This defines the flag for new routes.skipClean bool// If true, do not clear the request context after handling the request.// This has no effect when go1.7+ is used, since the context is stored// on the request itself.KeepContext bool// see Router.UseEncodedPath(). This defines a flag for all routes.useEncodedPath bool
}

调用NewRouter函数可用来实例化一个Router:

// NewRouter returns a new router instance.
func NewRouter() *Router {return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
}

这里可以看见,它开辟了一个装Route指针的map,然后默认该Router的KeepContextfalse,意思是在请求被处理完之后清除该请求的上下文。

2.HandleFunc函数

// HandleFunc registers a new route with a matcher for the URL path.
// See Route.Path() and Route.HandlerFunc().
func (r *Router) HandleFunc(path string, f func(http.ResponseWriter,*http.Request)) *Route {return r.NewRoute().Path(path).HandlerFunc(f)
}

若只观察HandleFunc函数,会发现其代码只有几行,其主要功能是使用URL的匹配器注册新路由。

gorilla/mux的HandleFunc函数功能很强大,主要有以下功能:

设置路由的HTTP方法

限制路由处理器只处理指定的HTTP方法的请求:

router.HandleFunc("/books/{title}", CreateBook).Methods("POST")
router.HandleFunc("/books/{title}", ReadBook).Methods("GET")
router.HandleFunc("/books/{title}", UpdateBook).Methods("PUT")
router.HandleFunc("/books/{title}", DeleteBook).Methods("DELETE")

上面的就是一组可以响应具体HTTP方法的RESTful风格的接口的路由。

设置路由的域名

限制路由处理器只处理访问指定域名加路由的请求:

router.HandleFunc("/books/{title}", BookHandler).Host("www.mybookstore.com")

限制HTTP 方案

将请求处理程序可响应的HTTP方案限制为http或者https

router.HandleFunc("/secure", SecureHandler).Schemes("https")
router.HandleFunc("/insecure", InsecureHandler).Schemes("http")

设置路径前缀和子路由

bookrouter := router.PathPrefix("/books").Subrouter()
bookrouter.HandleFunc("/", AllBooks)
bookrouter.HandleFunc("/{title}", GetBook)

3.PathPrefix函数

// PathPrefix registers a new route with a matcher for the URL path prefix.
// See Route.PathPrefix().
func (r *Router) PathPrefix(tpl string) *Route {return r.NewRoute().PathPrefix(tpl)
}

PathPrefix函数源码也只有几行,它的功能只是简单地增加URL的前缀,通常结合HandleFunc函数和Handler函数来使用。

五.References

  1. 基于 gorilla/mux 包实现路由定义和请求分发:基本使用
  2. gorilla/mux类库解析
  3. Gorilla源码分析之gorilla/mux源码分析
  4. 从一个例子分析gorilla/mux源码
  5. gorilla/mux官方GitHub

【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析相关推荐

  1. Flume 1.7 源码分析(三)程序入口

    Flume 1.7 源码分析(一)源码编译 Flume 1.7 源码分析(二)整体架构 Flume 1.7 源码分析(三)程序入口 Flume 1.7 源码分析(四)从Source写数据到Channe ...

  2. Netty源码分析系列之常用解码器(下)——LengthFieldBasedFrameDecoder

    扫描下方二维码或者微信搜索公众号菜鸟飞呀飞,即可关注微信公众号,Spring源码分析和Java并发编程文章. 前言 在上一篇文章中分析了三个比较简单的解码器,今天接着分析最后一个常用的解码器:Leng ...

  3. v56.05 鸿蒙内核源码分析(进程映像) | 程序是如何被加载运行的 | 百篇博客分析OpenHarmony源码

    子畏于匡,颜渊后.子曰:"吾以女为死矣."曰:"子在,回何敢死?" <论语>:先进篇 百篇博客系列篇.本篇为: v56.xx 鸿蒙内核源码分析(进程 ...

  4. 【SA8295P 源码分析】02 - SA8295P 整包镜像分析

    [SA8295P 源码分析]02 - SA8295P 整包镜像分析 一.UFS LUNs 二.开机启动相关镜像介绍 三.QNX Host相关镜像介绍 四.Android GVM 相关镜像介绍 五.其他 ...

  5. 【SA8295P 源码分析】16 - TouchScreen Panel (TP)线程函数 tp_recv_thread() 源码分析

    [SA8295P 源码分析]16 - TouchScreen Panel (TP)线程函数 tp_recv_thread 源码分析 一.TP 线程函数:tp_recv_thread() 二.处理&am ...

  6. 【SA8295P 源码分析】22 - QNX Ethernet MAC 驱动 之 emac_entry / emac_attach 函数源码分析

    [SA8295P 源码分析]22 - QNX Ethernet MAC 驱动 之 emac_entry / emac_attach 函数源码分析 一.EMAC:libdevnp-emac-eth.so ...

  7. 基于Golang的监听读取配置文件的程序包开发——simpleConfig_v1

    基于Golang的监听&读取配置文件的程序包开发--simpleConfig_v1 [阅读时间:约10分钟] 一.配置文件概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 ...

  8. 【源码分析】微信小程序 - 01表单组件 - 01button - 实践

    前言:此系列,结合Demo的源码,做一些实践和讨论: 1 Demo的效果: 微信小程序给出的button的Demo效果如上: 2 源码分析: 2.1 button.js js文件里面,定义了一些变量和 ...

  9. [授权发表]源码分析:静态分析 C 程序函数调用关系

    故事缘由 工欲善其事,必先利其器.今天我们来玩转一个小工具,叫 Callgraph,它可以把 C 语言的函数调用树(或者说流程图)画出来. 传统的命令行工具 Cscope,Ctags 可以结合vim ...

最新文章

  1. 用C++的random_shuffle()函数打乱int数组顺序
  2. clouderamanager-server启动,log日志中说需要mysql驱动的解决办法
  3. 各种编程语言的深度学习库整理
  4. 图解第一个Matlab仿真实例
  5. 5.intent_activity
  6. java给定_Java – 在给定示例中使用super()
  7. 分布式系统:SrpingBoot整合Zookeeper和Dubbo的版本匹配问题
  8. Python深入-Python的内存管理
  9. C#LeetCode刷题之#674-最长连续递增序列( Longest Continuous Increasing Subsequence)
  10. php curl如何解决分页,一段PHP的分页程序,报错,该如何解决
  11. 萌新关于C#委托一点见解
  12. Yii2中使用自定义的数据库
  13. java嗅探网页视频_网页视频嗅探器( API钩子 )
  14. PHP-Web聊天室 一天即可打造自己的聊天室-严双双-专题视频课程
  15. 锦天科技被盛大收购 23岁创始人成亿万富翁
  16. 如何设置条码标签的打印数量
  17. Java判断经纬度点是否在给定区域内
  18. openCV ROI
  19. leetcode 1277
  20. fread函数详解 函数原型

热门文章

  1. 高级教程: 作出动态决策和 Bi-LSTM CRF 重点
  2. python究竟要不要使用多线程
  3. Python---哈夫曼树---Huffman Tree
  4. PyTorch的十七个损失函数
  5. 如何通过HTTP优雅调用第三方-Feign
  6. 电子设计搜索引擎引入分析和见解
  7. 多传感器融合:自动驾驶(下)
  8. python3生成二维码中间带logo,有底图,可自定义文字
  9. 【CV】Anaconda 安装教程|CSDN创作打卡
  10. zen3架构_AMD Zen3架构处理器的L3缓存或将翻倍到64MB