以下是一个完整的 Server-Sent Events (SSE) 在 Go 中的实现示例,包含服务端和客户端的代码。SSE 适用于服务器向客户端单向推送实时数据的场景(如通知、日志流等)。
Server-Sent Events (SSE)
HTTP/2 + SSE
SSE Golang实现
1. 服务端代码(Go)
|  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 (
	"fmt"
	"log"
	"net/http"
	"time"
)
// SSE 事件流处理函数
func sseHandler(w http.ResponseWriter, r *http.Request) {
	// 设置响应头,表明是 SSE 流
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")
	// 创建一个通道用于模拟数据更新
	eventChan := make(chan string)
	defer close(eventChan)
	// 模拟异步数据生成(实际可能是数据库监听、MQ 订阅等)
	go func() {
		for i := 1; i <= 10; i++ {
			eventChan <- fmt.Sprintf("Event %d: %s", i, time.Now().Format("15:04:05"))
			time.Sleep(2 * time.Second) // 每 2 秒推送一次
		}
	}()
	// 监听客户端断开连接
	ctx := r.Context()
	for {
		select {
		case <-ctx.Done():
			log.Println("Client disconnected")
			return
		case event := <-eventChan:
			// 写入 SSE 格式的数据(data: 开头,结尾用 \n\n)
			_, err := fmt.Fprintf(w, "data: %s\n\n", event)
			if err != nil {
				log.Println("Write error:", err)
				return
			}
			// 刷新缓冲区,确保数据立即发送
			w.(http.Flusher).Flush()
		}
	}
}
func main() {
	http.HandleFunc("/sse", sseHandler)
	http.Handle("/", http.FileServer(http.Dir("./static"))) // 静态文件服务(放客户端 HTML)
	log.Println("Server started at :8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}
 | 
 
2. 客户端代码(HTML + JavaScript)
在项目目录下创建 static/index.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
 | <!DOCTYPE html>
<html>
<head>
    <title>SSE Demo</title>
</head>
<body>
    <h1>SSE 实时数据流</h1>
    <div id="events"></div>
    <script>
        const eventSource = new EventSource("/sse");
        // 监听服务器推送的事件
        eventSource.onmessage = (e) => {
            document.getElementById("events").innerHTML += `<p>${e.data}</p>`;
        };
        // 监听错误(如连接断开)
        eventSource.onerror = (e) => {
            console.error("SSE Error:", e);
            eventSource.close();
        };
    </script>
</body>
</html>
 | 
 
3. 运行步骤
- 创建项目目录结构:
| 1
2
3
4
 | your_project/
├── main.go
└── static/
    └── index.html
 |  
 
 
- 启动服务端:
- 打开浏览器访问 http://localhost:8080,页面将每 2 秒显示一条服务器推送的事件。
关键点说明
- SSE 协议格式:
 每条消息以data:开头,结尾用两个换行符\n\n(参考 MDN 规范)。
- 服务端要求:
- 必须设置 Content-Type: text/event-stream。
- 使用 Flush()立即发送数据。
 
- 客户端 API:
 浏览器原生支持EventSource,自动处理重连。
- 断开连接:
 服务端通过r.Context().Done()检测客户端是否断开。
扩展功能
- 自定义事件类型:
 服务端发送:
| 1
 | fmt.Fprintf(w, "event: customEvent\ndata: %s\n\n", "Custom Data")
 | 
 
客户端监听:
| 1
2
3
 | eventSource.addEventListener("customEvent", (e) => {
    console.log("Custom Event:", e.data);
});
 | 
 
- 重试机制:
 服务端可发送retry: 5000\n指定客户端重连间隔(毫秒)。
如果需要处理更复杂的场景(如鉴权),可以在 URL 中添加 token 或使用 Cookie。