MENU

Golang Gin框架中实现Server Sent Events(SSE)

January 2, 2024 • Read: 12396 • 默认分类

被这个功能困扰了好久,一直没实现,因为网上的Gin框架实现的SSE都非常复杂,写成了一整套复杂的中间件,经过研究,写出了一套精简的实现。

SSE接口代码, 发送信息修改sendEvents内代码即可:

func GetTaskResult(c *gin.Context) {
    tag := "compositioncontroller.GetTaskResult"
    ctx := xesgin.TransferToContext(c)
    var args proto.GetTaskResultReq
    err := c.ShouldBind(&args)
    if err != nil {
        logger.Ix(ctx, tag, "c.ShouldBind failed", "err:[%+v]", err)
        c.JSON(http.StatusOK, xesgin.Error(logger.NewError("", logger.PARAM_ERROR)))
        return
    }

    err = compositionSvc.NewCompositionSvc().TaskResultStream(ctx, args, c.Writer)
    if err != nil {
        logger.Ix(ctx, tag, "compositionSvc.GetTaskResultStreaming failed", "err:[%+v]", err)
        c.JSON(http.StatusOK, xesgin.Error(err))
        return
    }
}
// 流式响应任务结果
func (c *compositionSvc) TaskResultStream(ctx context.Context, args proto.GetTaskResultReq, w http.ResponseWriter) (err error) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")
    w.Header().Set("Access-Control-Allow-Origin", "*")

    closeNotifier := w.(http.CloseNotifier).CloseNotify()
    stopCh := make(chan struct{})

    go c.sendEvents(ctx, &args, w, stopCh)

    <-closeNotifier
    if _, ok := <-stopCh; ok {
        close(stopCh)
    }
    return
}
func (c *compositionSvc) sendEvents(ctx context.Context, args *proto.GetTaskResultReq, w http.ResponseWriter, stopCh chan struct{}) {
    tag := "compositionSvc.sendEvents"

    var resp proto.GetTaskResultResp
    for {
        var data []string
        select {
        case <-time.After(time.Millisecond * 300):
            data, err := redisRepo.Get(ctx, args.TaskId)
            if err != nil {
                logger.Ix(ctx, tag, "redisRepo.Get failed", "err:[%+v]", err)
                return
            }
            if data.Content == "" {
                continue
            }

            // 响应数据
            respByte, err := json.Marshal(resp)
            if err != nil {
                logger.Ix(ctx, tag, "json.Marshal failed", "err:[%+v]", err)
                return
            }
            sseData := fmt.Sprintf("data: %s\n\n", string(respByte))
            _, err = io.WriteString(w, sseData)
            if err != nil {
                logger.Ix(ctx, tag, "io.WriteString failed", "err:[%+v]", err)
                return
            }
            if flusher, ok := w.(http.Flusher); ok {
                flusher.Flush()
            }
            if data.status == cast.ToString(aigc.TaskStatusSuccess) || data.status == cast.ToString(aigc.TaskStatusFail) {
                return
            }
        case <-stopCh:
            return
        }
    }
}
Last Modified: January 3, 2024
Leave a Comment

41 Comments
  1. 2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
    新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
    新车首发,新的一年,只带想赚米的人coinsrore.com
    新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
    做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
    新车上路,只带前10个人coinsrore.com
    新盘首开 新盘首开 征召客户!!!coinsrore.com
    新项目准备上线,寻找志同道合的合作伙伴coinsrore.com
    新车即将上线 真正的项目,期待你的参与coinsrore.com
    新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
    新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com

  2. 新盘新项目,不再等待,现在就是最佳上车机会!

  3. 新车即将上线 真正的项目,期待你的参与

  4. 《宝贝》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/142249.html

  5. 如果因为害怕失败,而不去努力,那就不会有能够成功的人。