使用 Gin 框架来实现 SSE (Server-Sent Events)

使用 Gin 框架来实现 SSE (Server-Sent Events) 是一个非常常见的需求,因为 Gin 轻量、高效,非常适合构建 API 和实时服务。

SSE 的核心在于服务器需要保持一个长连接,并持续不断地向客户端推送数据。这与 Gin 默认的“请求-响应”模式有所不同,我们需要手动处理响应流的写入和连接的保持。

下面我将为你提供一个从简单到完整的实现方案,并附上详细解释和前端测试代码。


1. 核心概念回顾

在开始之前,我们再次明确 SSE 的几个关键点:

  1. 响应头: 服务器必须设置以下响应头:
    • Content-Type: text/event-stream: 告诉浏览器这是一个事件流。
    • Cache-Control: no-cache: 防止代理或浏览器缓存数据。
    • Connection: keep-alive: 保持 TCP 连接。
  2. 数据格式: 每条消息都必须遵循特定格式,以换行符结尾,并且一条完整的消息以一个空行(\n\n)结束。
    data: This is a message\n\n
    event: userLogin\ndata: {"id": 123}\n\n
    
  3. 刷新缓冲区: 在写入数据后,必须手动调用 http.ResponseWriterFlush() 方法,将数据立即发送给客户端,而不是等待缓冲区填满。

2. 方案一:基础实现

这个方案将演示最基本的 SSE 设置:一个端点,每秒向客户端发送一个包含时间戳的消息。

服务器端代码 (main.go)
package main

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
)

func main() {
   
   
	// 创建一个默认的 Gin 引擎
	r := gin.Default()

	// 定义 SSE 端点
	r.GET("/sse", func(c *gin.Context) {
   
   
		// 1. 设置响应头
		c.Header("Content-Type", "text/event-stream")
		c.Header("Cache-Control", "no-cache")
		c.Header("Connection", "keep-alive")
		// 允许跨域 (如果前端不在同一个源)
		c.Header("Access-Control-Allow-Origin", "*")

		// 2. 获取底层的 http.ResponseWriter
		// 我们需要它来调用 Flush()
		w := c.Writer

		// 3. 创建一个通道,用于在客户端断开连接时通知循环结束
		notify := w.CloseNotify()

		// 4. 循环发送消息
		for i := 0; ; i++ {
   
   
			select {
   
   
			case <-notify:
				// 如果客户端断开连接,退出循环
				log.Println("Client closed the connection.")
				return
			default:
				// 5. 格式化并发送消息
				// 每条消息必须以 \n\n 结尾
				message := fmt.Sprintf("data: Message %d at %s\n\n", i, time.Now().Format(time.RFC3339))
				_, err := w.Write([]byte(message))
				if err != nil {
   
   
					log.Printf("Error writing to client: %v", err)
					return // 如果写入出错,也退出循环
				}

				// 6. 刷新缓冲区,将数据立即发送给客户端
				w.Flush()

				// 等待一秒
				time.Sleep(1 * time.Second)
			}
		}
	})

	// 启动服务器
	log.Println("SSE server started at http://localhost:8080/sse")
	if err := r.Run(":8080"); err != nil {
   
   
		log.Fatal
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值