赞
踩
文章概要:本文主要通过一个demo来介绍如何使用Go语言实现SSE中转。
本文内容来自:谷流仓AI - ai.guliucang.com
mkdir go-app && cd go-app
# 后面的模块名自己定义
go mod init example/user/go-app
先看一下完成之后的目录结构:
go-app/
├─ go.mod
├─ http/
│ ├─ requests.go
│ └─ responses.go
└─ main.go
然后每个文件的代码如下:
package main import ( "example/user/go-app/http" "github.com/gin-gonic/gin" "log" ) // 主函数:初始化并启动 Gin 框架的 HTTP 服务器,支持 /event-stream 的 POST 和 GET 请求。 func main() { // 创建一个用于传递事件的通道 ch := make(chan string) // 初始化并配置默认的 Gin路由器 router := gin.Default() // 设置 POST /event-stream 的处理函数,用于处理 POST 请求 router.POST("/event-stream", func(c *gin.Context) { http.HandleEventStreamPost(c, ch) // 处理 POST 请求的逻辑 }) // 设置 GET /event-stream 的处理函数,用于处理 GET 请求 router.GET("/event-stream", func(c *gin.Context) { http.HandleEventStreamGet(c, ch) // 处理 GET 请求的逻辑 }) // 启动 HTTP 服务器并监听端口 9990,记录启动失败的错误日志 log.Fatalf("error running HTTP server: %s\n", router.Run(":9990")) }
package http import ( "errors" "fmt" "github.com/gin-gonic/gin" "io" ) // EventStreamRequest 结构体定义了事件流请求的数据模型 type EventStreamRequest struct { Message string `form:"message" json:"message" binding:"required,max=100"` // 请求中必须提供的消息内容,最大长度为100 } // HandleEventStreamPost 处理POST方法的事件流请求 // c: Gin框架的上下文对象,用于处理HTTP请求和响应 // ch: 用于事件流通信的通道,将请求消息发送到此通道 func HandleEventStreamPost(c *gin.Context, ch chan string) { var request EventStreamRequest // 尝试绑定请求数据到EventStreamRequest结构体 if err := c.ShouldBind(&request); err != nil { // 如果绑定失败,生成错误响应并返回 errorMessage := fmt.Sprintf("request validation error: %s", err.Error()) BadRequestResponse(c, errors.New(errorMessage)) return } // 将请求消息发送到通道 ch <- request.Message // 创建成功响应并返回 CreatedResponse(c, &request.Message) return } // HandleEventStreamGet 处理获取事件流的请求。 // c: Gin框架的上下文对象,用于处理HTTP请求和响应。 // ch: 一个字符串类型的通道,用于向客户端发送事件消息。 func HandleEventStreamGet(c *gin.Context, ch chan string) { // 使用Stream方法来建立一个服务器端事件流,不断检查通道中是否有新消息。 c.Stream(func(w io.Writer) bool { // 如果通道中有消息,通过SSEvent方法以"message"事件类型发送到客户端。 if msg, ok := <-ch; ok { c.SSEvent("message", msg) return true // 表示继续发送下一个事件 } return false // 表示没有更多事件,结束流 }) return }
package http import ( "github.com/gin-gonic/gin" "net/http" ) // JSendFailResponse 定义了一个失败响应的结构体,包含状态和数据字段 type JSendFailResponse[T any] struct { Status string `json:"status"` // 响应状态 Data T `json:"data"` // 响应数据,这里泛型T可以是任意类型 } // JSendSuccessResponse 定义了一个成功响应的结构体,包含状态和可选的数据字段 type JSendSuccessResponse[T any] struct { Status string `json:"status"` // 响应状态 Data T `json:"data,omitempty"` // 响应数据,成功时可选 } // BadRequestResponse 用于处理Bad Request错误,返回400状态码和错误信息 func BadRequestResponse(c *gin.Context, error error) { c.JSON( http.StatusBadRequest, JSendFailResponse[string]{ Status: "fail", // 设置响应状态为失败 Data: error.Error(), // 将错误信息填入数据字段 }, ) return } // CreatedResponse 用于处理创建资源的成功响应,返回201状态码和创建的资源信息 func CreatedResponse[T interface{}](c *gin.Context, i *T) { c.JSON( http.StatusCreated, JSendSuccessResponse[T]{ Status: "success", // 设置响应状态为成功 Data: *i, // 填入创建的资源信息 }, ) return }
go run main.go
curl http://localhost:9990/event-stream
curl -d '{"message":"Hello, Event Stream!"}' -H "Content-Type: application/json" -X POST http://localhost:9990/event-stream
event:message
data:Hello, Event Stream!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。