发布于:,更新于:

08.Mygin中间件优化及logger日志中间件

本篇是mygin的第八篇,参照gin框架,Mygin从零开始完全手写,在实现的同时,带你一窥gin框架的核心原理实现。

目的

  • 中间件Middleware优化
  • 默认log日志中间件
    在上篇 Mygin实现中间件Middleware 中间件Middleware很生硬,完全依赖循环,如果某个中间件想要cover住全部中间件,比如我想记录,整个请求的耗时时间,以便针对优化的功能。因此需要把之前生硬的方式做一些修改。

修改

1.实例化上下文修改
1
2
3
4
5
6
7
8
//实例化一个下上文
c := &Context{
Request: r,
Writer: w,
Params: params,
handlers: handlers,
index: -1, //默认下标为-1
}
2.修改上下文Next方法
1
2
3
4
5
6
7
8
9
10
// Next 执行链中的剩余处理程序。
func (c *Context) Next() {
c.index++
//遍历handlers
for c.index < int8(len(c.handlers)) {
//真正调用执行handler方法
c.handlers[c.index](c)
c.index++
}
}

日志

参照(复制)gin中的写法,新建mygin/logger.go日志中间件文件。

  • mygin/logger.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
    80
    package mygin

    import (
    "fmt"
    "net/http"
    "time"
    )

    const (
    green = "\033[97;42m" // 绿色
    white = "\033[90;47m" // 白色
    yellow = "\033[90;43m" // 黄色
    red = "\033[97;41m" // 红色
    blue = "\033[97;44m" // 蓝色
    magenta = "\033[97;45m" // 洋红色
    cyan = "\033[97;46m" // 青色
    reset = "\033[0m" // 重置颜色
    )

    type LogFormatterParams struct {
    }

    // MethodColor 方法颜色获取
    func (l *LogFormatterParams) MethodColor(method string) string {
    switch method {
    case http.MethodGet:
    return blue
    case http.MethodPost:
    return cyan
    case http.MethodPut:
    return yellow
    case http.MethodDelete:
    return red
    case http.MethodPatch:
    return green
    case http.MethodHead:
    return magenta
    case http.MethodOptions:
    return white
    default:
    return reset
    }
    }

    // StatusCodeColor 状态颜色获取
    func (l *LogFormatterParams) StatusCodeColor(code int) string {
    switch {
    case code >= http.StatusOK && code < http.StatusMultipleChoices:
    return green
    case code >= http.StatusMultipleChoices && code < http.StatusBadRequest:
    return white
    case code >= http.StatusBadRequest && code < http.StatusInternalServerError:
    return yellow
    default:
    return red
    }
    }

    // LoggerFunc 记录日志的方法
    func (l *LogFormatterParams) LoggerFunc() HandlerFunc {
    return func(context *Context) {
    // 启动时间
    start := time.Now()

    // 后续处理请求
    context.Next()

    //后续处理请求 结束时间
    now := time.Now()

    str := fmt.Sprintf("[MyGIN] %v |%s %3d %s| %13v |%s %-7s %s %#v\n",
    now.Format("2006/01/02 - 15:04:05"),
    l.StatusCodeColor(context.status), context.status, reset,
    now.Sub(start), //耗时
    l.MethodColor(context.Request.Method), context.Request.Method, reset,
    context.Request.URL.Path,
    )
    fmt.Println(str)
    }
    }
    日志中间件

测试

测试代码

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
package mygin

import (
"net/http"
"path"
"testing"
)

func TestMyGin06(t *testing.T) {
r := Default()
r.Use()
//测试需要登录
group := r.Group("/api", func(context *Context) {
//todo....
context.String(http.StatusOK, "api Group 中间件失败了....\n")
context.Abort()
})

group.Use()

//这个回调不会执行
group.GET("/hello/:name", func(context *Context) {
name := context.Params.ByName("name")
context.String(http.StatusOK, path.Join("hello ", name, "!"))
})

//测试没有发生Abort
group2 := r.Group("/api2", func(context *Context) {
//todo....
context.String(http.StatusOK, "api Group 中间件成功了....\n")
})

//这个回调会执行
group2.GET("/hello2/:name", func(context *Context) {
name := context.Params.ByName("name")
context.String(http.StatusOK, path.Join("hello2 ", name, "!\n"))
})

// 启动服务器并监听端口
r.Run(":8088")
}
启动测试
1
go test
curl请求测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
curl -i http://localhost:8088/api2/hello2/scott
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Tue, 30 Jan 2024 06:56:03 GMT
Content-Length: 49

api Group 中间件成功了....
hello2 /scott/!
➜ ~ curl -i http://localhost:8088/api/hello/scott
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Tue, 30 Jan 2024 06:56:26 GMT
Content-Length: 33

api Group 中间件失败了....
查看控制台输出

mygin08.png




本站由 [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/) 许可协议,转载请注明出处。