为了账号安全,请及时绑定邮箱和手机立即绑定

我无法用自动收报机逃避 for 循环

我无法用自动收报机逃避 for 循环

Go
qq_笑_17 2022-10-10 17:53:25
我有这个 API 可以扫描驱动程序的位置并每 1 秒通过 web-socket 发送它们。问题是客户端断开连接时无法逃脱循环。它似乎永远活着。我正在将 Gin 与 nhooyr websocket 库一起使用。var GetDriverLocations = func(c *gin.Context) {    wsoptions := websocket.AcceptOptions{InsecureSkipVerify: true}    wsconn, err := websocket.Accept(c.Writer, c.Request, &wsoptions)    if err != nil {        return    }    defer wsconn.Close(websocket.StatusInternalError, "the sky is falling")    driverLocation := &models.DriverLocation{}    ticker := time.NewTicker(time.Second)    defer ticker.Stop()    for {        select {        case <-ticker.C:        case <-c.Request.Context().Done():            fmt.Println("done") //this never gets printed            return        }        coords, err := driverLocation.GetDrivers()        if err != nil {            break        }        err = wsjson.Write(c.Request.Context(), wsconn, &coords)        if websocket.CloseStatus(err) == websocket.StatusNormalClosure {            break        }        if err != nil {            break        }    }    fmt.Println("conn ended") //this never gets printed}我也试过这个循环,但也有同样的问题:for range ticker.C{    coords, err := driverLocation.GetDrivers()    if err != nil {        break    }    err = wsjson.Write(c.Request.Context(), wsconn, &coords)    if websocket.CloseStatus(err) == websocket.StatusNormalClosure {        break    }    if err != nil {        break    }}
查看完整描述

1 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

因为网络连接被 nhooyr websocket 库从 net/http 服务器劫持,所以在c.Request.Context()处理程序返回之前不会取消上下文。


调用CloseRead以获取在连接关闭时取消的上下文。在循环中使用该上下文。


var GetDriverLocations = func(c *gin.Context) {


    wsoptions := websocket.AcceptOptions{InsecureSkipVerify: true}

    wsconn, err := websocket.Accept(c.Writer, c.Request, &wsoptions)

    if err != nil {

        return

    }

    defer wsconn.Close(websocket.StatusInternalError, "")

    ctx := wsconn.CloseRead(c.Request.Context())


    driverLocation := &models.DriverLocation{}


    ticker := time.NewTicker(time.Second)

    defer ticker.Stop()


    for {

        select {

        case <-ticker.C:

        case <-ctx.Done():

            return

        }

        coords, err := driverLocation.GetDrivers()

        if err != nil {

            break

        }

        err = wsjson.Write(c.Request.Context(), wsconn, &coords)

        if err != nil {

            break

        }

    }

}



查看完整回答
反对 回复 2022-10-10
  • 1 回答
  • 0 关注
  • 135 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号