This is an explanation of the video content.
 用技术延续对ACG的热爱
4
 | 
Go实现推送数据到前端

Go

Go原生实现

client.html

<!DOCTYPE html>
<html>

<head>
    <title>Server-Sent Events Example</title>
</head>

<body>
    <h1>Server-Sent Events Example</h1>
    <div id="sse-data"></div>

    <script>
        // 创建一个 EventSource 对象,连接到服务器端的 SSE
        var eventSource = new EventSource('server.php');

        // 监听 message 事件,接收来自服务器端的数据
        eventSource.addEventListener('message', function (event) {
            // 在页面上展示接收到的数据
            document.getElementById('sse-data').innerHTML = event.data;
        });
    </script>
</body>

</html>

server.go

package main

import (
	"fmt"
	"math/rand"
	"net/http"
	"time"
)

func main() {
	http.HandleFunc("/", eventStreamHandler)
	http.ListenAndServe(":8080", nil)
}

func eventStreamHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-store")

	counter := rand.Intn(10) + 1

	ctx := r.Context() // Get the request context

	for {
		select {
		case <-ctx.Done():
			// Client closed the connection
			return
		default:
			// Continue streaming events

			// Send a "ping" event every second
			fmt.Fprintf(w, "event: ping\n")
			curDate := time.Now().Format("2006-01-02T15:04:05")
			fmt.Fprintf(w, "data: {\"time\": \"%s\"}\n", curDate)
			fmt.Fprintf(w, "\n")

			// Send a simple message at random intervals
			counter--

			if counter == 0 {
				fmt.Fprintf(w, "data: This is a message at time %s\n", curDate)
				fmt.Fprintf(w, "\n")
				counter = rand.Intn(10) + 1
			}

			// Flush the HTTP response buffer
			flusher, ok := w.(http.Flusher)
			if ok {
				flusher.Flush()
			}

			time.Sleep(1 * time.Second)
		}
	}
}

Gin版本

server.go

package main

import (
	"fmt"
	"math/rand"
	"time"

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

func main() {
	r := gin.Default()
	r.GET("/", eventStreamHandler)
	r.Run(":8080")
}

func eventStreamHandler(ctx *gin.Context) {
	ctx.Writer.Header().Set("Content-Type", "text/event-stream")
	ctx.Writer.Header().Set("Cache-Control", "no-store")
	ctx.Writer.Header().Set("Connection", "keep-alive")

	counter := rand.Intn(10) + 1

	for {
		select {
		case <-ctx.Request.Context().Done():
			// Client closed the connection
			return
		default:
			// Continue streaming events

			// Send a "ping" event every second
			ctx.SSEvent("ping", gin.H{
				"time": time.Now().Format("2006-01-02T15:04:05"),
			})

			// Send a simple message at random intervals
			counter--
			if counter == 0 {
				ctx.SSEvent("message", fmt.Sprintf("This is a message at time %s", time.Now().Format("2006-01-02T15:04:05")))
				counter = rand.Intn(10) + 1
			}

			ctx.Writer.Flush()
			time.Sleep(1 * time.Second)
		}
	}
}



4 服务端 ↦ Go开发技巧 __ 288 字
 Go开发技巧 #2