[golang gin框架] 3.路由详解,自定义控制器,中间件

一.路由详解

路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET、POST 等)组成的,涉及到应用如何响应客户端对某个网站节点的访问,前面介绍了路由基础以及路由配置,这里详细讲讲路由传值、路由返回值
  1. GET POST 以及获取 Get Post 传值

(1).Get 请求传值

// GET /user?uid=20&page=1
router.GET("/user", func(c *gin.Context) {
    uid := c.Query("uid")
    page := c.DefaultQuery("page", "0")
    c.String(200, "uid=%v page=%v", uid, page)
})

(2).动态路由传值

// 域名/user/20
r.GET("/user/:uid", func(c *gin.Context) {
    uid := c.Param("uid")
    c.String(200, "userID=%s", uid)
})

(3).Post 请求传值 获取 form 表单数据

// 定义一个 default/add_user.html 的页面
{{ define "default/add_user.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/doAddUser" method="post">
用户名:<input type="text" name="username" />
密码: <input type="password" name="password" />
<input type="submit" value="提交">
</form>
</body>
</html>
{{end}}
// 通过 c.PostForm 接收表单传过来的数据
router.GET("/addUser", func(c *gin.Context) {
    c.HTML(200, "default/add_user.html", gin.H{})
})
router.POST("/doAddUser", func(c *gin.Context) {
    username := c.PostForm("username")
    password := c.PostForm("password")
    age := c.DefaultPostForm("age", "20")
    c.JSON(200, gin.H{ 
        "usernmae": username,
         "password": password,
         "age": age,
     })
})

(4).获取 GET POST 传递的数据绑定到结构体

为了能够更方便的获取请求相关参数,提高开发效率,可以基于请求的 Content-Type
识别请求数据类型并利用反射机制自动提取请求中 QueryString、form 表单、JSON、XML 等
参数到结构体中,下面的示例代码演示了.ShouldBind()强大的功能,它能够基于请求自动提
取 JSON、form 表单和 QueryString 类型的数据,并把值绑定到指定的结构体对象
//注意首字母大写
type Userinfo struct {
    Username string `form:"username" json:"user"` 
    Password string `form:"password" json:"password"`
 }

Get 传值绑定到结构体

//?username=zhangsan&password=123456
router.GET("/", func(c *gin.Context) {
    var userinfo Userinfo
    if err := c.ShouldBind(&userinfo); err == nil {
        c.JSON(http.StatusOK, userinfo)
    } else {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    }
})
//返回数据
{"user":"zhangsan","password":"123456"}

Post 传值绑定到结构体

router.POST("/doLogin", func(c *gin.Context) {
    var userinfo Userinfo
    if err := c.ShouldBind(&userinfo); err == nil {
        c.JSON(http.StatusOK, userinfo)
    } else {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
})
//返回数据
{"user":"zhangsan","password":"123456"}

(5).获取 Post Xml 数据

在 API 的开发中,经常会用到 JSON 或 XML 来作为数据交互的格式,这个时候可以在 gin 中使用 c.GetRawData()获取数据
<?xml version="1.0" encoding="UTF-8"?>
<article>
<content type="string">我是张三</content>
<title type="string">张三</title>
</article>
type Article struct {
    Title string `xml:"title"`
    Content string `xml:"content"`
}

router.POST("/xml", func(c *gin.Context) {
    b, _ := c.GetRawData() // 从 c.Request.Body 读取请求数据
    article := &Article{}
    if err := xml.Unmarshal(b, &article); err == nil {
        c.JSON(http.StatusOK, article)
    } else {
        c.JSON(http.StatusBadRequest, err.Error())
    }
})

代码汇总:

main.go

package main

import (
    "github.com/gin-gonic/gin"
    "html/template"
    "net/http"
    "time"
)

//时间戳转换成日期函数
func UnixToTime(timestamp int) string {
    t := time.Unix(int64(timestamp), 0)
    return t.Format("2006-01-02 15:04:05")
}

func Println(str1 string, str2 string) string {
    return str1 + str2
}

type UserInfo struct {
    Username string `json:"username" form:"username"`
    Password string `json:"password" form:"password"`
}

type Article struct {
    Title   string `json:"title" xml:"title"`
    Content string `json:"content" xml:"content"`
}

func main() {
    //初始化路由
    r := gin.Default()
    //自定义模板函数,必须在r.LoadHTMLGlob前面
    r.SetFuncMap(template.FuncMap{
        "UnixToTime": UnixToTime, //注册模板函数
        "Println":    Println,
    })
    //加载templates中所有模板文件, 使用不同目录下名称相同的模板,注意:一定要放在配置路由之前才得行
    r.LoadHTMLGlob("templates/**/*")
    //配置静态web目录 第一个参数表示路由,第二个参数表示映射的目录
    r.Static("/static", "./static")
    //配置路由
    //GET传值
    r.GET("/", func(c *gin.Context) {
        username := c.Query("username")
        age := c.Query("age")
        page := c.DefaultQuery("page", "1")
        c.JSON(http.StatusOK, gin.H{
            "username": username,
            "age":      age,
            "page":     page,
        })
    })
    //GET传值 获取文章id
    r.GET("/article", func(c *gin.Context) {
        id := c.DefaultQuery("id", "1")
        c.JSON(http.StatusOK, gin.H{
            "id":     id,
            "conent": "文章详情",
        })
    })

    //post演示
    r.GET("/user", func(c *gin.Context) {
        //渲染模板
        c.HTML(http.StatusOK, "default/user.html", gin.H{})
    })
    //获取表单post过来的数据
    r.POST("/doAddUser", func(c *gin.Context) {
        username := c.PostForm("username")
        password := c.PostForm("password")
        age := c.DefaultPostForm("age", "20")
        c.JSON(http.StatusOK, gin.H{
            "username": username,
            "password": password,
            "age":      age,
        })
    })
    //获取GET POST传递的数据绑定到结构体
    //r.POST("/getUser", func(c *gin.Context) {
    r.GET("/getUser", func(c *gin.Context) {
        user := &UserInfo{}
        //绑定到对应的结构体
        if err := c.ShouldBind(&user); err == nil {
            c.JSON(http.StatusOK, user)
        } else {
            c.JSON(http.StatusOK, gin.H{
                "err": err.Error(),
            })
        }
    })
    //获取 POST xml数据绑定到结构体
    r.POST("/xml", func(c *gin.Context) {
        article := &Article{}
        //获取c.Request.Body读取请求数据, 返回的是一个xml切片
        xmlSliceData, _ := c.GetRawData()
        //解析xml切片
        if err := xml.Unmarshal(xmlSliceData, &article); err == nil {
            c.JSON(http.StatusOK, article)
        } else {
            c.JSON(http.StatusBadRequest, gin.H{
                "err": err.Error(),
            })
        }
    })

    //动态路由传值
    //http://127.0.0.1:8080/list/2221  http://127.0.0.1:8080/list/2
    r.GET("/list/:id", func(c *gin.Context) {
        id := c.Param("id")
        c.JSON(http.StatusOK, gin.H{
            "id": id,
        })
    })
    r.Run() // 启动一个web服务
}

default/user.html

<!-- 相当于给模板定义一个名字, define end 必须成对出现 -->
{{ define "default/user.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>news</title>
</head>
<body>
{{ template "public/page_header.html" .}}
<form action="/doAddUser" method="post">
    用户名:<input type="text" name="username" /> <br/> <br/>
    密码:<input type="text" name="password" /><br/> <br/>
    <input type="submit" value="提交">
</form>
{{ template "public/page_footer.html" .}}
</body>
</html>
{{ end }}
  1. 简单的路由组

官方文档: https://gin-gonic.com/zh-cn/docs/examples/grouping-routes/
func main() {
    //初始化路由
    r := gin.Default()
    //简单的路由分组
    defaultRouters := r.Group("/")
    {
        defaultRouters.GET("/", func(c *gin.Context) {
            c.String(200, "首页")
        })
        defaultRouters.GET("/news", func(c *gin.Context) {
            c.String(200, "新闻")
        })
    }
    
    apiRouters := r.Group("/api")
    {
        apiRouters.GET("/", func(c *gin.Context) {
            c.String(200, "api首页")
        })
        apiRouters.GET("/userlist", func(c *gin.Context) {
            c.String(200, "一个userlist接口")
        })
    }
    
    adminRouters := r.Group("/admin")
    {
        adminRouters.GET("/", func(c *gin.Context) {
            c.String(200, "后台首页")
        })
        adminRouters.GET("/user", func(c *gin.Context) {
            c.String(200, "用户列表")
        })
        adminRouters.GET("/article", func(c *gin.Context) {
            c.String(200, "新闻列表")
        })
    }
}

3.Gin 路由文件 分组

(1).新建 routes 文件夹,routes 文件下面新建 adminRoutes.go、apiRoutes.go、defaultRoutes.go

1).新建 adminRoutes.go
package routers

import "github.com/gin-gonic/gin"

//设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {
    adminRouters := r.Group("/admin")
    {
        adminRouters.GET("/", func(c *gin.Context) {
            c.String(200, "后台首页")
        })
        adminRouters.GET("/user", func(c *gin.Context) {
            c.String(200, "用户列表")
        })
        adminRouters.GET("/article", func(c *gin.Context) {
            c.String(200, "新闻列表")
        })
    }
}
2).新建 apiRoutes.go
package routers

import "github.com/gin-gonic/gin"

//设置api路由
func ApiRoutersInit(r *gin.Engine) {
    apiRouters := r.Group("/api")
    {
        apiRouters.GET("/", func(c *gin.Context) {
            c.String(200, "api首页")
        })
        apiRouters.GET("/userlist", func(c *gin.Context) {
            c.String(200, "一个userlist接口")
        })
    }
}
3).新建 defaultRoutes.go
package routers

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

//设置前台后台路由
func DefaultRoutersInit(r *gin.Engine) {
    defaultRouters := r.Group("/")
    {
        defaultRouters.GET("/", func(c *gin.Context) {
            c.HTML(http.StatusOK, "default/index.html", gin.H{
                "msg":"前台首页",
            })
        })
        defaultRouters.GET("/news", func(c *gin.Context) {
            c.String(200, "新闻")
        })
    }
}

(2).配置 main.go

package main

import (
    "gindemo/routers"
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    //路由文件
    routers.AdminRoutersInit(r)
    routers.ApiRoutersInit(r)
    routers.DefaultRoutersInit(r)
}

二.Gin 中自定义控制器

1.控制器分组

当项目比较大的时候有必要对控制器进行分组

(1).新建 controller/admin/articleController.go

package admin

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

type ArticleController struct {
    
}

func (con ArticleController) Index(c *gin.Context) {
    c.String(http.StatusOK, "文章列表1")
}

func (con ArticleController) Add(c *gin.Context) {
    c.String(http.StatusOK, "文章添加2")
}

func (con ArticleController) Edit(c *gin.Context) {
    c.String(http.StatusOK, "文章编辑3")
}

(2).新建 controller/admin/indexController.go

package admin

import "github.com/gin-gonic/gin"

type IndexController struct {
    
}

func (con IndexController) Index(c *gin.Context) {
    c.String(200, "后台首页")
}

(3).新建 controller/admin/userController.go

package admin

import "github.com/gin-gonic/gin"

//定义一个UserController结构体,可以实例化结构体访问里面的方法
type UserController struct {
  
}

func (con UserController) Index(c *gin.Context) {
    //c.String(200, "用户列表1")
    con.success(c)
}

func (con UserController) Add(c *gin.Context) {
    c.String(200, "用户添加2")
}

func (con UserController) Edit(c *gin.Context) {
    c.String(200, "用户编辑3")
}

(4).配置对应的路由:adminRoutes.go

package routers

import (
    "gindemo/controllers/admin"
    "github.com/gin-gonic/gin"
)

//设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {
    adminRouters := r.Group("/admin")
    {
        adminRouters.GET("/", admin.IndexController{}.Index)// 实例化控制器,并访问其中方法

        adminRouters.GET("/user", admin.UserController{}.Index)
        adminRouters.GET("/user/add",admin.UserController{}.Add)
        adminRouters.GET("/user/edit", admin.UserController{}.Edit)

        adminRouters.GET("/article", admin.ArticleController{}.Index)
        adminRouters.GET("/article/add", admin.ArticleController{}.Add)
        adminRouters.GET("/article/edit", admin.ArticleController{}.Edit)
    }
}
其他路由的配置方法类似

2.控制器的继承

(1).新建 controller/admin/baseController.go

package admin

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

//基础控制器
type BaseController struct {

}

func (con BaseController) success(c *gin.Context) {
    c.String(http.StatusOK, "成功")
}

func (con BaseController) error(c *gin.Context) {
    c.String(http.StatusOK, "失败")
}

(2).userController 继承 baseController

package admin

import "github.com/gin-gonic/gin"

//定义一个UserController结构体,可以实例化结构体访问里面的方法
type UserController struct {
    BaseController  // 继承基础控制器
}

func (con UserController) Index(c *gin.Context) {
    con.success(c)
}

func (con UserController) Add(c *gin.Context) {
    c.String(200, "用户添加2")
}

func (con UserController) Edit(c *gin.Context) {
    c.String(200, "用户编辑3")
}

三.Gin 中间件

Gin 框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数,这个钩子函
数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、
记录日志、耗时统计等
通俗的讲:中间件就是匹配路由前和匹配路由完成后执行的一系列操作

1.路由中间件

(1).初识中间件

Gin 中的中间件必须是一个 gin.HandlerFunc 类型,配置路由的时候可以传递多个 func 回调函
数,最后一个 func 回调函数前面触发的方法都可以称为中间件
package main
import ( 
    "fmt"
    "github.com/gin-gonic/gin"
)

//中间件
func initMiddleware(c *gin.Context)  {
    c.String(200, "--1.中间件one--")
}

func main() {
    //初始化路由
    r := gin.Default()
    //加载templates中所有模板文件, 使用不同目录下名称相同的模板,注意:一定要放在配置路由之前才得行
    r.LoadHTMLGlob("templates/**/*")
    //配置静态web目录 第一个参数表示路由,第二个参数表示映射的目录
    r.Static("/static", "./static")

    //路由分组
    defaultRouters := r.Group("/")
    {
        defaultRouters.GET("/", initMiddleware, func(c *gin.Context) {
            c.String(200, "首页")
        })
    }

    r.Run() // 启动一个web服务
}

(2)c.Next()调用该请求的剩余处理程序

package main
import ( 
    "fmt"
    "github.com/gin-gonic/gin"
)

//中间件
func initMiddleware(c *gin.Context)  {
    start := time.Now().UnixNano()
    c.String(200, "--1.中间件one--")
    //调用该请求的剩余处理程序
    c.Next()

    c.String(200, "--2.中间件one--")
    end := time.Now().UnixNano()
    // 计算耗时 Go 语言中的 Since()函数保留时间值,并用于评估与实际时间的差异
    fmt.Println( end - start)
}

func main() {
    //初始化路由
    r := gin.Default()
    //加载templates中所有模板文件, 使用不同目录下名称相同的模板,注意:一定要放在配置路由之前才得行
    r.LoadHTMLGlob("templates/**/*")
    //配置静态web目录 第一个参数表示路由,第二个参数表示映射的目录
    r.Static("/static", "./static")

    //路由分组
    defaultRouters := r.Group("/")
    {
        //中间件访问,调用该请求的剩余处理程序, c.Next(): 依次输出:--1.中间件one--首页--2.中间件one--
        defaultRouters.GET("/", initMiddleware, func(c *gin.Context) {
            c.String(200, "首页")
        })
    }

    r.Run() // 启动一个web服务
}

(3).一个路由配置多个中间件的执行顺序

package main
import ( 
    "fmt"
    "github.com/gin-gonic/gin"
)

//中间件
func initMiddleware(c *gin.Context)  {
    start := time.Now().UnixNano()
    c.String(200, "--1.中间件one--")
    //调用该请求的剩余处理程序
    c.Next()

    c.String(200, "--2.中间件one--")
    end := time.Now().UnixNano()
    // 计算耗时 Go 语言中的 Since()函数保留时间值,并用于评估与实际时间的差异
    fmt.Println( end - start)
}
//中间件
func initMiddlewareTwo(c *gin.Context)  {
    start := time.Now().UnixNano()
    c.String(200, "--2.中间件two--")
    //调用该请求的剩余处理程序
    c.Next()
    c.String(200, "--2.中间件two--")
    end := time.Now().UnixNano()
    fmt.Println( end - start)
}

func main() {
    //初始化路由
    r := gin.Default()
    //加载templates中所有模板文件, 使用不同目录下名称相同的模板,注意:一定要放在配置路由之前才得行
    r.LoadHTMLGlob("templates/**/*")
    //配置静态web目录 第一个参数表示路由,第二个参数表示映射的目录
    r.Static("/static", "./static")

    //路由分组
    defaultRouters := r.Group("/")
    {
        //多个中间件访问: 依次输出:--1.中间件one----2.中间件two--首页--2.中间件two----2.中间件one--
        defaultRouters.GET("/", initMiddleware, initMiddlewareTwo, func(c *gin.Context) {
            c.String(200, "首页")
        })
    }

    r.Run() // 启动一个web服务
}
控制台内容:
initMiddleware--1-执行中间件
initMiddlewareTwo--1-执行中间件
执行路由里面的程序
initMiddlewareTwo--2-执行中间件
initMiddleware--2-执行中间件

(4).c.Abort()终止调用该请求的剩余处理程序

Abort 是终止的意思, c.Abort() 表示终止调用该请求的剩余处理程序
package main
import ( 
    "fmt"
    "github.com/gin-gonic/gin"
)

//中间件
func initMiddlewareAbort(c *gin.Context)  {
    start := time.Now().UnixNano()
    c.String(200, "--1.中间件abort--")
    //调用该请求的剩余处理程序
    //c.Next()
    //终止该请求的剩余处理程序
    c.Abort()

    c.String(200, "--2.中间件abort--")
    end := time.Now().UnixNano()
    fmt.Println( end - start)
}

func main() {
    //初始化路由
    r := gin.Default()
    //加载templates中所有模板文件, 使用不同目录下名称相同的模板,注意:一定要放在配置路由之前才得行
    r.LoadHTMLGlob("templates/**/*")
    //配置静态web目录 第一个参数表示路由,第二个参数表示映射的目录
    r.Static("/static", "./static")

    //路由分组
    defaultRouters := r.Group("/")
    {
       //中间件访问,终止该请求的剩余处理程序, c.Abort(): 依次输出:--1.中间件abort----2.中间件abort--
       //不会执行最后的HandFunc程序
        defaultRouters.GET("/", initMiddlewareAbort, func(c *gin.Context) {
            c.String(200, "首页")
        })
    }

    r.Run() // 启动一个web服务
}    

2.全局中间件

package main
import ( 
    "fmt"
    "github.com/gin-gonic/gin"
)


//中间件
func initMiddleware(c *gin.Context)  {
    start := time.Now().UnixNano()
    c.String(200, "--1.中间件one--")
    //调用该请求的剩余处理程序
    c.Next()
    //终止该请求的剩余处理程序
    //c.Abort()

    c.String(200, "--2.中间件one--")
    end := time.Now().UnixNano()
    fmt.Println( end - start)
}

//中间件
func initMiddlewareAbort(c *gin.Context)  {
    start := time.Now().UnixNano()
    c.String(200, "--1.中间件abort--")
    //调用该请求的剩余处理程序
    //c.Next()
    //终止该请求的剩余处理程序
    c.Abort()

    c.String(200, "--2.中间件abort--")
    end := time.Now().UnixNano()
    fmt.Println( end - start)
}


//中间件
func initMiddlewareTwo(c *gin.Context)  {
    start := time.Now().UnixNano()
    c.String(200, "--2.中间件two--")
    //调用该请求的剩余处理程序
    c.Next()
    //终止该请求的剩余处理程序
    //c.Abort()

    c.String(200, "--2.中间件two--")
    end := time.Now().UnixNano()
    fmt.Println( end - start)
}

func main() {
    //初始化路由
    r := gin.Default()
    //加载templates中所有模板文件, 使用不同目录下名称相同的模板,注意:一定要放在配置路由之前才得行
    r.LoadHTMLGlob("templates/**/*")
    //配置静态web目录 第一个参数表示路由,第二个参数表示映射的目录
    r.Static("/static", "./static")
    
    //全局中间件
    r.Use(initMiddleware, initMiddlewareTwo)
    //路由分组
    defaultRouters := r.Group("/")
    {
       //中间件访问,终止该请求的剩余处理程序, c.Abort(): 依次输出:--1.中间件abort----2.中间件abort--
       //不会执行最后的HandFunc程序
        defaultRouters.GET("/", initMiddlewareAbort, func(c *gin.Context) {
            c.String(200, "首页")
        })
    }

    r.Run() // 启动一个web服务
}

3.在路由分组中配置中间件

(1).为路由组注册中间件有以下两种写法

写法 1:
userGroup := r.Group("/user", UserOper())
{
    userGroup.GET("/index", func(c *gin.Context) {
        ...
    })
    ... 
}
写法 2:
userGroup := r.Group("/user")
userGroup.Use(UserOper())
{
    userGroup.GET("/index", func(c *gin.Context) {
        ...
    })
    ... 
}

(2).分组路由adminRoutes.go 中配置中间件

adminRoutes.go
package routers

import (
    "gindemo/controllers/admin"
    "gindemo/middlewares"
    "github.com/gin-gonic/gin"
)

//设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {
    //路由分组: 配置全局中间件:middlewares.InitMiddleware
    adminRouters := r.Group("/admin", middlewares.InitMiddleware)
    {
        adminRouters.GET("/", admin.IndexController{}.Index)// 实例化控制器,并访问其中方法

        adminRouters.GET("/user", admin.UserController{}.Index)
        adminRouters.GET("/user/add",admin.UserController{}.Add)
        adminRouters.GET("/user/edit", admin.UserController{}.Edit)

        adminRouters.GET("/article", admin.ArticleController{}.Index)
        adminRouters.GET("/article/add", admin.ArticleController{}.Add)
        adminRouters.GET("/article/edit", admin.ArticleController{}.Edit)
    }
}
middlewares/init.go
package middlewares

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "time"
)

func InitMiddleware( c *gin.Context)  {
    //判断用户是否登录
    fmt.Println(time.Now())
    fmt.Println(c.Request.URL)
}

4.中间件和对应控制器之间共享数据

(1).设置值

c.Set("username","张三")

(2).获取值

username, _ := c.Get("username")

(3).中间件设置值

middlewares/init.go
package middlewares

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "time"
)

func InitMiddleware( c *gin.Context)  {
    //判断用户是否登录
    fmt.Println(time.Now())
    fmt.Println(c.Request.URL)
    //设置值, 和对应控制器之间共享数据
    c.Set("username", "张三")
}
控制器获取值 controlelers/adimn/indexController.go
package admin

import (
    "fmt"
    "github.com/gin-gonic/gin"
)

type IndexController struct {
    
}

func (con IndexController) Index(c *gin.Context) {
    //获取中间件中设置的username值,数据共享
    username, _ := c.Get("username")
    fmt.Println(username)
    //username是一个空接口类型,故要使用则需要用类型断言转换username
    v, ok := username.(string)
    if ok != true {
        c.String(200, "后台首页--获取用户名失败")
    } else {
        c.String(200, "后台首页,用户名:" + v)
    }

}

5.中间件注意事项

(1).gin 默认中间件

gin.Default()默认使用了 Logger 和 Recovery 中间件,其中:
• Logger 中间件将日志写入 gin.DefaultWriter,即使配置了 GIN_MODE=release
• Recovery 中间件会 recover 任何 panic,如果有 panic 的话,会写入 500 响应码
如果不想使用上面两个默认的中间件,可以使用 gin.New()新建一个没有任何默认中间件的
路由

(2).gin 中间件中使用 goroutine

当在中间件或 handler 中启动新的 goroutine 时, 不能使用原始的上下文(c *gin.Context),必须使用其只读副本(c.Copy())
package middlewares

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "time"
)

func InitMiddleware( c *gin.Context)  {
    //判断用户是否登录
    fmt.Println(time.Now())
    fmt.Println(c.Request.URL)
    //设置值, 和对应控制器之间共享数据
    c.Set("username", "张三")

    //gin 中间件中使用 goroutine
    //当在中间件或 handler 中启动新的 goroutine 时,不能使用原始的上下文(c *gin.Context),
    //必须使用其只读副本(c.Copy())
    cCp := c.Copy()
    go func() {
        time.Sleep(2 * time.Second)
        fmt.Println("gin 中间件中使用 goroutine" + cCp.Request.URL.Path)
    }()
}

[上一节][golang gin框架] 2.Gin HTML模板渲染以及模板语法,自定义模板函数,静态文件服务

[下一节][golang gin框架] 4.自定义Model以及Gin 文件上传

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值