• Mygin中间件优化及logger日志中间件


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

    目的

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

    修改

    1.实例化上下文修改
    //实例化一个下上文
    	c := &Context{
    		Request:  r,
    		Writer:   w,
    		Params:   params,
    		handlers: handlers,
    		index:    -1, //默认下标为-1
    	}
    
    2.修改上下文Next方法
    // 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
    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)
    	}
    }
    

    日志中间件

    测试

    测试代码

    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")
    }
    
    启动测试
    go test
    
    curl请求测试
    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 中间件失败了....
    
    查看控制台输出


    __EOF__

  • 本文作者: pengb
  • 本文链接: https://www.cnblogs.com/pengb/p/17997152
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    瑞吉外卖(部署维护篇)
    【打工日常】使用docker部署个人实时在线文档协助编辑器
    JavaEE——No.2 套接字编程(TCP)
    c语言动态内存分布
    48MySQL数据库基础
    关系运算符3(阁瑞钛伦特软件-九耶实训)
    鸿蒙Next-Scroll滚动
    MySQL数据库优化总结
    RocketMQ—RocketMQ发送同步、异步、单向、延迟、批量、顺序、批量消息、带标签消息
    施耐德电气:勾勒未来工业愿景,赋能中国市场
  • 原文地址:https://www.cnblogs.com/pengb/p/17997152