发布于:,更新于:

02.Mygin实现简单的路由

本文是Mygin第二篇

目的:

  • 实现路由映射
  • 提供了用户注册静态路由方法(GET、POST方法)

基于上一篇 Mygin 实现简单Http 且参照Gin

  • 使用了map数组实现简单路由的映射关系
  • 不同的method对应一个组,Gin框架初始化时map时初始化9个,因为支持的http.method刚好为9个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package http
//Gin 中对应的9个方法
const (
MethodGet = "GET"
MethodHead = "HEAD"
MethodPost = "POST"
MethodPut = "PUT"
MethodPatch = "PATCH" // RFC 5789
MethodDelete = "DELETE"
MethodConnect = "CONNECT"
MethodOptions = "OPTIONS"
MethodTrace = "TRACE"
)

mygin路由功能实现

  • mygin/engine.go
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    package mygin

    import (
    "log"
    "net/http"
    )

    type Engine struct {
    trees methodTrees
    }

    // 路由树
    type methodTrees map[string]methodTree

    // 路由节点
    type methodTree struct {
    method string
    paths map[string]http.HandlerFunc
    }

    // 获取路由root根
    func (e *Engine) getRoot(method string) methodTree {
    if root, ok := e.trees[method]; ok {
    return root
    }
    e.trees[method] = methodTree{method: method, paths: make(map[string]http.HandlerFunc)}
    return e.trees[method]
    }

    // 添加路由方法
    func (e *Engine) addRoute(method, path string, handler http.HandlerFunc) {
    root := e.getRoot(method)

    //是否已经在路由数上绑定,如果已经绑定就不在继续绑定
    if _, ok := root.paths[path]; ok {
    log.Default().Println(path, "is exist")
    return
    }
    //将path与处理方法关系绑定
    root.method = method
    root.paths[path] = handler

    }

    func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    //对应method中的路由树
    if tree, ok := e.trees[r.Method]; ok {
    //路由数中path映射
    if handler, ok := tree.paths[r.URL.Path]; ok {
    handler(w, r)
    return
    }
    }
    //在路由数中没有找到对应的路由
    w.Write([]byte("404 Not found!\n"))
    }

    // Get Get方法
    func (e *Engine) Get(path string, handler http.HandlerFunc) {
    e.addRoute(http.MethodGet, path, handler)
    }

    // Post Post方法
    func (e *Engine) Post(path string, handler http.HandlerFunc) {
    e.addRoute(http.MethodPost, path, handler)
    }

    // Default returns an Engine
    func Default() *Engine {
    return &Engine{trees: make(methodTrees, 2)}
    }

    // Run 启动方法start a http server
    func (e *Engine) Run(addr string) {
    err := http.ListenAndServe(addr, e)
    if err != nil {
    return
    }
    }
    我们重点介绍一下这部分的实现
  • 首先定义了类型methodTrees,这是提供给框架用户的,用来定义路由映射的处理方法。我们在Engine中,添加了一张路由映射表router,key 由请求方法和静态路由地址构成,例如GET请求 “/“ 在methodTrees中methodTrees[“GET”][“/“]、”/hello”=>methodTrees[“GET”][“/hello”]、”/hello”=>methodTrees[“POST”][“/hello”],这样针对相同的路由,如果请求方法不同,可以映射不同的处理方法(Handler),value 是用户映射的处理方法。
  • 当用户调用(*Engine).Get()方法时,会将路由和处理方法注册到映射表 router 中,(*Engine).Run()方法,是 ListenAndServe 的包装。
  • Engine实现的 ServeHTTP 方法的作用就是,解析请求的路径,查找路由映射表,如果查到,就执行注册的处理方法。如果查不到,就返回 **404 Not found!**。

mai测试n方法调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"mygin"
"net/http"
)

func main() {
engine := mygin.Default()

engine.Get("/hello", func(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte("Mygin Get hello method"))
})

engine.Post("/hello", func(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte("Mygin Post hello method"))
})

engine.Run(":8088")
}

curl请求测试

1
2
3
4
5
6
~ curl 127.0.0.1:8088/hello
Mygin Get hello method#
~ curl -X POST http://127.0.0.1:8088/hello
Mygin Post hello method#
~ curl -X POST http://127.0.0.1:8088/hello2
404 Not found!

至此,整个Mygin框架的原型已经出来了。实现了路由映射表,提供了用户注册静态路由的方法,包装了启动服务的函数。当然,到目前为止,我们还没有实现比net/http标准库更强大的能力,不用担心,很快就可以将动态路由、中间件等功能添加上去了。




本站由 [PengBin](/) 使用 [Stellar 1.26.3](https://github.com/xaoxuu/hexo-theme-stellar/tree/1.26.3) 主题创建。 本博客所有文章除特别声明外,均采用 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) 许可协议,转载请注明出处。