【问题标题】:How to write a stream API using gin-gonic server in golang? Tried c.Stream didnt work如何在 golang 中使用 gin-gonic 服务器编写流 API?试过 c.Stream 没用
【发布时间】:2017-12-03 03:52:32
【问题描述】:

我想在 golang 中使用 gin-gonic 服务器创建一个流式 API。

func StreamData(c *gin.Context) {
    chanStream := make(chan int, 10)
    go func() {for i := 0; i < 5; i++ {
        chanStream <- i
        time.Sleep(time.Second * 1)
    }}()
    c.Stream(func(w io.Writer) bool {
        c.SSEvent("message", <-chanStream)
        return true
    })
}

router.GET("/stream", controller.StreamData)

但是当我试图到达终点时,它只是卡住了,没有响应。 是否有人使用了流功能,以便他/她可以指出我可能正在做的错误。谢谢!

【问题讨论】:

  • 解决了这个问题。在SSEvent之后,返回true就是让stream函数继续运行,在channel通信完成后,我们需要在stream关闭后返回false。
  • 但是现在的问题是,在时间流函数运行之前,调用者并没有得到任何流数据,只有在c.Stream函数完成后才能得到。

标签: api go streaming goroutine go-gin


【解决方案1】:

如果流结束,您应该返回 false。并关闭chan。

package main

import (
    "io"
    "time"

    "github.com/gin-gonic/contrib/static"
    "github.com/gin-gonic/gin"
    "github.com/mattn/go-colorable"
)

func main() {
    gin.DefaultWriter = colorable.NewColorableStderr()
    r := gin.Default()
    r.GET("/stream", func(c *gin.Context) {
        chanStream := make(chan int, 10)
        go func() {
            defer close(chanStream)
            for i := 0; i < 5; i++ {
                chanStream <- i
                time.Sleep(time.Second * 1)
            }
        }()
        c.Stream(func(w io.Writer) bool {
            if msg, ok := <-chanStream; ok {
                c.SSEvent("message", msg)
                return true
            }
            return false
        })
    })
    r.Use(static.Serve("/", static.LocalFile("./public", true)))
    r.Run()
}

附加

客户端代码应该是:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>
var stream = new EventSource("/stream");
stream.addEventListener("message", function(e){
    console.log(e.data);
});
</script>    
</body>
</html>

【讨论】:

  • 非常感谢。已经弄清楚了。(问题下方的cmets)但现在我面临一个不同的问题,直到时间流函数运行,调用者没有得到任何流数据,它只有在c.Stream函数完成后才会得到。如果你能帮助我,那就太好了。
  • 你的意思是从chan读取的数据可能会在响应超时后出现?
  • 目前在当前的实现中,点击“/stream”的系统会在 5 秒后收到数据。一口气完成所有 5 个事件。我想要的是调用系统应该每秒开始接收事件,响应应该看起来像接收者的流 API。我希望这次我对问题陈述很清楚。
  • 真的吗?我确保我的实现每秒消耗每个响应。
  • 发现问题....在 gin 路由器中使用 gzip 压缩。它不允许它流式传输事件。评论了它,现在可以正常工作了。
猜你喜欢
  • 2016-11-03
  • 1970-01-01
  • 2021-06-13
  • 2019-03-14
  • 2017-07-01
  • 2020-03-29
  • 1970-01-01
  • 2015-08-22
  • 1970-01-01
相关资源
最近更新 更多