效果演示
在和机器人对话时,经常都是流式方式,这里使用hertz的SSE来实现一个流式接口。最终效果如下

代码实现
1、依赖
1 2 |
go get github.com/cloudwego/hertz@latest go get github.com/hertz-contrib/sse@latest |
2、 后端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package main import ( "context" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/common/hlog" "github.com/hertz-contrib/sse" "time" ) func main() { h := server.Default(server.WithHostPorts(":8888")) h.GET("/stream-chat", func(c context.Context, ctx *app.RequestContext) { // 1. 创建 SSE 流 stream := sse.NewStream(ctx) // 2. 设置响应头(NewStream 会自动设置部分头,但建议显式声明) ctx.SetContentType("text/event-stream; charset=utf-8") ctx.Response.Header.Set("Cache-Control", "no-cache") ctx.Response.Header.Set("Connection", "keep-alive") ctx.Response.Header.Set("Access-Control-Allow-Origin", "*") // 3. 获取请求参数 question := ctx.Query("q") hlog.Infof("收到新请求 - 问题: %s", question) responses := []string{ "正在分析你的问题...", "处理中,请稍候...", "初步结论:需要进一步检查。", "总结:解决方案已找到!", "流式对话完成。", } for index, resp := range responses { // 构建SSE格式数据(注意末尾的\n\n) event := &sse.Event{ Event: "message", Data: []byte(resp), } hlog.Infof("message %v:%v", index, resp) err := stream.Publish(event) if err != nil { hlog.Infof("err : %s", err) } time.Sleep(1 * time.Second) // 模拟处理延迟 } }) h.Spin() } |
3、 前端 chat.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!-- 新增字符集声明 --> <title>NewStream 流式对话演示</title> <style> /* 添加中文字体支持 */ body { font-family: "Microsoft YaHei", SimHei, sans-serif; } </style> </head> <body> <h1>实时对话流1 </h1> <input type="text" id="question" placeholder="输入问题"> <button onclick="startStream()">开始对话</button> <div id="output" style="white-space: pre-wrap; margin-top: 20px;"></div> <script> let eventSource = null; function startStream() { if (eventSource) { eventSource.close(); } const question = document.getElementById('question').value || "默认问题"; const outputDiv = document.getElementById('output'); outputDiv.innerHTML = ''; // 强制UTF-8编码 const url = `http://localhost:8888/stream-chat?q=${encodeURIComponent(question)}`; eventSource = new EventSource(url); // 处理消息事件 eventSource.addEventListener('message', (e) => { const data = e.data; // 直接使用 e.data outputDiv.innerHTML += `${data}\n`; outputDiv.scrollTop = outputDiv.scrollHeight; }); // 处理错误 eventSource.onerror = (e) => { console.error('SSE错误:', e); outputDiv.innerHTML += '--- 连接已关闭 ---\n'; eventSource.close(); }; } </script> </body> </html> |