首页
学习
活动
专区
圈层
工具
发布
16 篇文章
1
Go 语言 Web 编程系列(一)—— 快速入门:创建第一个 Web 应用
2
Go 语言 Web 编程系列(二)—— HTTP 请求处理的底层运行机制
3
Go 语言 Web 编程系列(三)—— 基于官方标准库自定义路由处理器
4
Go 语言 Web 编程系列(四)—— 基于 gorilla/mux 包实现路由定义:基本使用篇
5
Go 语言 Web 编程系列(五)—— 基于 gorilla/mux 包实现路由匹配:进阶使用篇
6
Go 语言 Web 编程系列(六)—— 基于 gorilla/mux 包实现路由匹配:路由中间件
7
Go 语言 Web 编程系列(七)—— 基于 gorilla/mux 包实现路由匹配:处理静态资源响应
8
Go 语言 Web 编程系列(八)—— 基于 gorilla/mux 包实现路由匹配:服务 SPA 应用
9
Go 语言 Web 编程系列(九)—— 基于 gorilla/mux 包实现路由匹配:通过 CORS 处理跨域请求
10
Go 语言 Web 编程系列(十)—— 基于 gorilla/mux 包实现路由匹配:健康检查与接口测试
11
Go 语言 Web 编程系列(十一)—— 仿照 Laravel 框架对 Go 路由代码进行拆分
12
Go 语言 Web 编程系列(十二)—— 通过 Request 读取 HTTP 请求报文
13
Go 语言 Web 编程系列(十三)—— 获取用户请求数据(上)
14
Go 语言 Web 编程系列(十四)—— 获取用户请求数据(下)
15
Go 语言 Web 编程系列(十五)—— 通过 ResponseWriter 接口创建 HTTP 响应
16
Go 语言 Web 编程系列(十六)—— 设置、读取和删除 Cookie

Go 语言 Web 编程系列(四)—— 基于 gorilla/mux 包实现路由定义:基本使用篇

1、功能简介

前面我们介绍了 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 中的路由分组),以便不同路由可以共享通用条件,比如主机、路径前缀等。

2、使用入门

开始使用 mux.Router 之前,需要安装这个扩展包:

代码语言:javascript
复制
go get -u github.com/gorilla/mux
代码语言:javascript
复制

然后在我们可以这样实现创建第一个Web应用中演示的注册路由:

代码语言:javascript
复制
代码语言:javascript
复制
package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

func sayHelloWorld(w http.ResponseWriter, r *http.Request)  {
    w.WriteHeader(http.StatusOK)  // 设置响应状态码为 200
    fmt.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,即可渲染出如下结果:

代码语言:javascript
复制
Hello, World!
代码语言:javascript
复制

3、路由参数

现在,我们想要在路由定义中设置路由参数,例如 /hello/world/hello/学院君,这可以通过如下方式来实现:

代码语言:javascript
复制
r.HandleFunc("/hello/{name}", sayHelloWorld)
代码语言:javascript
复制

你甚至还可以通过正则表达式限制参数字符:

代码语言:javascript
复制
代码语言:javascript
复制
r.HandleFunc("/hello/{name:[a-z]+}", sayHelloWorld)

以上规则表示路由参数只能是小写字母,不支持其它字符。

相应地,在闭包处理函数中,我们需要这样解析路由参数:

代码语言:javascript
复制
func sayHelloWorld(w http.ResponseWriter, r *http.Request)  {
    params := mux.Vars(r)
    w.WriteHeader(http.StatusOK)  // 设置响应状态码为 200
    fmt.Fprintf(w, "Hello, %s!", params["name"])  // 发送响应到客户端
}
代码语言:javascript
复制

重启服务器,这次,我们可以通过 http://localhost:8080/hello/xueyuanjun 这种方式请求路由了:

代码语言:javascript
复制
Hello, xueyuanjun!
代码语言:javascript
复制

如果参数中包含中文,则返回 404 响应,表示路由匹配失败:

4、自定义处理器

http.ServeMux 一样,在 mux.Router 中,还可以将请求转发到自定义的处理器类,而不是闭包函数:

代码语言:javascript
复制
package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

func sayHelloWorld(w http.ResponseWriter, r *http.Request)  {
    params := mux.Vars(r)
    w.WriteHeader(http.StatusOK)  // 设置响应状态码为 200
    fmt.Fprintf(w, "Hello, %s!", params["name"])  // 发送响应到客户端
}

type HelloWorldHandler struct {}

func (handler *HelloWorldHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)  {
    params := mux.Vars(r)
    w.WriteHeader(http.StatusOK)  // 设置响应状态码为 200
    fmt.Fprintf(w, "你好, %s!", params["name"])  // 发送响应到客户端
}

func main()  {
    r := mux.NewRouter()
    r.HandleFunc("/hello/{name:[a-z]+}", sayHelloWorld)
    r.Handle("/zh/hello/{name}", &HelloWorldHandler{})
    log.Fatal(http.ListenAndServe(":8080", r))
}

上篇教程介绍的自定义路由处理器一样,这里自定义的 HelloWorldHandler 也要实现 Handler 接口声明的 ServeHTTP 方法,调用方式和之前一样,只是需要通过 r.Handle 方法,因为第二个参数传入的是处理器实例,而不是闭包函数。

重启服务器,我们就可以访问如下 HTTP 路由了:

以上,就是 gorilla/mux 扩展包提供的路由器 mux.Router 的基本使用,下篇教程,我们继续介绍它的更多路由匹配功能,包括限定主机、请求方法、scheme、路径前缀、请求头、查询字符串等,通过 mux.Router,我们甚至可以构建出比 Laravel 路由还要强大的路由匹配规则。

下一篇
举报
领券