登录
首页 >  Golang >  Go问答

事件处理的 Gin 中间件

来源:stackoverflow

时间:2024-03-07 18:51:25 289浏览 收藏

积累知识,胜过积蓄金银!毕竟在Golang开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《事件处理的 Gin 中间件》,就带大家讲解一下知识点,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~

问题内容

我正在尝试为 gin 服务器制作中间件来处理单个请求期间的事件,因为我需要上下文中的 ip 地址之类的东西,并且为了不传递整个上下文,我宁愿传递我的侦听器,这使得我的方法不依赖关于 gin.context

我设置了服务器

func main() {
    router := gin.new()
    router.use(gin.recovery())
    api := router.group("api", middleware())
    {
        api.get("test/:id", endpoint)
    }
    router.run("localhost:8080")
}

并制作了一个中间件

func middleware() gin.handlerfunc {
    return func(c *gin.context) {
        listener := make(chan int)
        c.set("eventlistener", listener)
        go func() {
            select {
            case <-listener:
                fmt.println("event called")
            default:
                fmt.println("default")
            }
        }()
        c.next()
    }
}

然后我得到了一个端点,我可以在其中获取侦听器,然后将其传递给我想要的任何函数

func endpoint(c *gin.context) {
    listener := c.mustget("eventlistener").(chan int)

    id := c.param("id")
    idint, err := strconv.parseint(id, 10, 64)
    if err != nil {
        fmt.println(err)
        return
    }
    dosomething(listener, int(idint))
}

dosomething 函数显示稍后不使用上下文

func dosomething(listener chan int, id int) {
    if id == 1 {
        fmt.println("error: cause event and exit")
        listener <- int(id)
        return
    }
    if id == 2 {
        fmt.println("warn: cause event but continue")
        listener <- int(id)
    }
    fmt.println("ok: everything is fine")
}

现在的工作方式是:

当你调用 get http://localhost:8080/api/test/1 时,它将触发事件并退出

当您调用 get http://localhost:8080/api/test/2 时,它将触发事件并继续工作

当您调用 get http://localhost:8080/api/test/3 时,它不会触发事件,因为一切正常。

因此,一切正常,但仅适用于请求中的一个事件。您不能调用另一个,因为 select 已经通过了,所以我的问题是如何修复它并允许多次触发事件。

我知道我可以做到这一点

for {
    select {
    case <-listener:
        fmt.println("event called")
    }
}

但是这个循环的停止条件是什么?

我知道有类似 c.done() 的东西,它是 chan 但不知道如何在我的情况下使用它,因为我可以使它像

for {
    select {
    case <-listener:
        fmt.Println("event called")
    case <-c.Done():
        return
    }
}

但是如何传递 c.done() 呢?这个goroutine不会停止。


解决方案


我发现还有 c.request.context().done() 现在可以工作,停止 goroutine 并允许处理多个事件

go func() {
    for {
        select {
        case <-listener:
            fmt.Println("event called")
        case <-c.Request.Context().Done():
            return
        }
    }
}()

文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《事件处理的 Gin 中间件》文章吧,也可关注golang学习网公众号了解相关技术文章。

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>