GO GIN SSE DEMO

devtools/2024/11/15 1:42:09/

文章目录

      • 接口描述:
          • 1.1 `/events/time` - 时间流
          • 1.2 `/events/numbers` - 数字流
        • 2. 用户管理接口
          • 2.1 `/user/:id` - 获取用户信息
          • 2.2 `/user` - 创建用户
      • 项目结构
        • 1. `main.go`
        • 2. 创建 `handlers/event_time.go`
        • 3. 创建 `handlers/event_number.go`
        • 4. `handlers/user.go`
        • 5. 运行服务器
      • 小结

将GIN项目与SSE库结合,写一个简单的demo,具备正常的API接口和流处理接口,实现了两种类型的 Server-Sent Events (SSE) 流,以及一个简单的用户管理接口。

下面是对每个接口的详细描述:

接口描述:

####1. SSE 接口

1.1 /events/time - 时间流
  • 功能:每秒向客户端发送一次当前的时间。
  • 路径/events/time
  • 请求方式GET
  • 返回格式SSE(文本事件流 text/event-stream
  • 数据内容:每条消息包含当前时间,格式为 RFC3339,例如:data: 2024-09-14T15:00:00Z
  • 实现细节
    • 使用 Gin 处理 HTTP 请求。
    • 设置 HTTP 头以指示客户端进行流式传输。
    • 通过 for 循环持续发送当前时间,并使用 flusher.Flush() 刷新输出缓冲区,确保数据实时传送到客户端。
    • 每次发送时间后,等待 1 秒钟。
1.2 /events/numbers - 数字流
  • 功能:每 2 秒向客户端发送一个递增的数字。
  • 路径/events/numbers
  • 请求方式GET
  • 返回格式SSE(文本事件流 text/event-stream
  • 数据内容:每条消息包含一个递增的数字,例如:data: 0data: 1data: 2 等。
  • 实现细节
    • 与时间流相似,设置 HTTP 头并初始化 SSE 传输。
    • 使用 for 循环持续发送递增的数字,每发送一次数字后,等待 2 秒钟。
2. 用户管理接口
2.1 /user/:id - 获取用户信息
  • 功能:根据用户 ID 获取用户信息。
  • 路径/user/:id
  • 请求方式GET
  • 参数
    • id:用户的唯一标识符,通过 URL 参数传递。
  • 返回格式:JSON
  • 数据内容:返回包含用户 ID 和名称的 JSON 对象,例如:{"user_id": "1", "name": "John Doe"}
  • 实现细节
    • 从 URL 中获取用户 ID。
    • 假设从数据库或其他数据源获取用户信息,当前示例中返回了硬编码的用户信息。
2.2 /user - 创建用户
  • 功能:创建一个新的用户。
  • 路径/user
  • 请求方式POST
  • 请求体:JSON 格式,包含用户名称,例如:{"name": "Alice"}
  • 返回格式:JSON
  • 数据内容:返回新创建的用户信息,包括用户 ID 和名称,例如:{"user_id": "12345", "name": "Alice"}
  • 实现细节
    • 解析请求体中的 JSON 数据,获取用户名称。
    • 验证数据是否合法。
    • 假设将用户信息存储到数据库或其他存储系统,当前示例中返回了硬编码的用户 ID 和名称。

项目结构

project/
│
├── main.go
├── handlers/
│   ├── event_number.go
│   ├── event_time.go
│   ├── user.go
1. main.go

main.go 文件会引入所有的路由注册函数,包括 event_timeevent_number

package mainimport ("project/handlers""github.com/gin-gonic/gin"
)func main() {router := gin.Default()// 注册 SSE 路由handlers.RegisterEventTimeRoutes(router)handlers.RegisterEventNumberRoutes(router)// 注册用户路由handlers.RegisterUserRoutes(router)router.Run(":8080")
}
2. 创建 handlers/event_time.go

event_time.go 文件只处理时间流的 SSE 接口。

package handlersimport ("fmt""net/http""time""github.com/gin-gonic/gin"
)func RegisterEventTimeRoutes(router *gin.Engine) {router.GET("/events/time", timeStream)
}// 时间流
func timeStream(c *gin.Context) {c.Writer.Header().Set("Content-Type", "text/event-stream")c.Writer.Header().Set("Cache-Control", "no-cache")c.Writer.Header().Set("Connection", "keep-alive")flusher, ok := c.Writer.(http.Flusher)if !ok {c.String(http.StatusInternalServerError, "Streaming unsupported!")return}for {// 发送当前时间fmt.Fprintf(c.Writer, "data: %s\n\n", time.Now().Format(time.RFC3339))flusher.Flush()time.Sleep(1 * time.Second)}
}
3. 创建 handlers/event_number.go

event_number.go 文件只处理数字流的 SSE 接口。

package handlersimport ("fmt""net/http""time""github.com/gin-gonic/gin"
)func RegisterEventNumberRoutes(router *gin.Engine) {router.GET("/events/numbers", numbersStream)
}// 数字流
func numbersStream(c *gin.Context) {c.Writer.Header().Set("Content-Type", "text/event-stream")c.Writer.Header().Set("Cache-Control", "no-cache")c.Writer.Header().Set("Connection", "keep-alive")flusher, ok := c.Writer.(http.Flusher)if !ok {c.String(http.StatusInternalServerError, "Streaming unsupported!")return}number := 0for {// 发送递增的数字fmt.Fprintf(c.Writer, "data: %d\n\n", number)flusher.Flush()number++time.Sleep(2 * time.Second)}
}
4. handlers/user.go

user.go 文件保持不变,用于处理用户相关的接口。

package handlersimport ("net/http""github.com/gin-gonic/gin"
)func RegisterUserRoutes(router *gin.Engine) {router.GET("/user/:id", getUser)router.POST("/user", createUser)
}func getUser(c *gin.Context) {userId := c.Param("id")// 假设在这里处理获取用户信息的逻辑c.JSON(http.StatusOK, gin.H{"user_id": userId,"name":    "John Doe",})
}func createUser(c *gin.Context) {var json struct {Name string `json:"name" binding:"required"`}if err := c.ShouldBindJSON(&json); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}// 假设在这里处理创建用户的逻辑c.JSON(http.StatusCreated, gin.H{"user_id": "12345","name":    json.Name,})
}
5. 运行服务器
  1. main.goevent_time.goevent_number.gouser.go 保存到项目中。

  2. 运行项目:

    go run main.go
    
  3. 服务器将在 localhost:8080 上运行。

小结

  • 模块化:将每个 SSE 接口拆分到单独的文件中,可以提高代码的可读性和可维护性。
  • 路由注册:在 main.go 中分别调用 RegisterEventTimeRoutesRegisterEventNumberRoutes 注册各自的路由。
  • 灵活扩展:这种结构可以很容易地扩展新的 SSE 接口,只需创建新的文件并注册路由。

这样做可以让每个文件更专注于自己的任务,保持代码清晰整洁,有利于团队合作和代码维护。


http://www.ppmy.cn/devtools/114932.html

相关文章

中国IT产业的新挑战与新机遇

近日,科技巨头IBM中国宣布撤出在华两大研发中心,这一消息在IT行业引起了广泛关注和讨论。跨国公司的这一决策不仅影响了众多IT从业者的职业发展,也引发了关于中国IT产业在全球竞争中的地位和未来发展方向的深入思考。  一、跨国公司决策背后…

C++游戏

宠粉福利&#xff01; 目录 1.猜数字 2.五子棋 3.打怪 4.跑酷 5.打飞机 6.扫雷 1.猜数字 #include <iostream> #include <cstdlib> #include <ctime>int main() {std::srand(static_cast<unsigned int>(std::time(0))); // 设置随机数种子int …

leetcode-枚举算法

1.两数之和 题目一&#xff1a;两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素…

【Windows 同时安装 MySQL5 和 MySQL8 - 详细图文教程】

卸载 MySQL 参考文章&#xff1a; 完美解决Mysql彻底删除并重装_怎么找到mysql并卸载-CSDN博客使用命令卸载mysql_卸载mysql服务命令-CSDN博客 先管理员方式打开 cmd &#xff0c;切换到 MySQL 安装目录的 bin 文件夹下&#xff0c;执行如下命令&#xff0c;删除 MySQL 服务mys…

人工智能与机器学习原理精解【24】

文章目录 统计机器学习最大似然估计&#xff08;Maximum Likelihood Estimation&#xff0c;MLE&#xff09;基本原理一、原理概述二、工作步骤三、应用实例四、性质与局限性 求解步骤示例 正态分布&#xff08;Normal Distribution&#xff09;定义公式性质应用注意事项 最大似…

【L1.第六章】Appium 如何定位与页面等待实战

PythonAppiumPytest 自动化测试教程 1、App 自动化应用控制1.1、启动1.2、关闭 2、常见控件定位方法2.1、控件定位方式2.2、控件查找方法 find_elements & find_element2.3、常用定位方式 3、 强制等待与隐式等待3.1、强制等待3.2、隐式等待3.3、显式等待 1、App 自动化应用…

我Github的问题解决了!

看的这篇&#xff0c;解决使用git时遇到Failed to connect to github.com port 443 after 21090 ms: Couldn‘t connect to server_git couldnt connect to server-CSDN博客 之前想推送的能推送了&#xff0c;拉取的也能取了。 一、如果是在挂着梯子的情况下拉取或者推送代码…

北银金科:北京银行“金融操作系统”建设项目

在数字经济的背景下,金融服务体系以数据为关键生产要素、以科技为核心生产工具、以平台生产为主要生产方式,需要一个类似于计算机操作系统的金融操作系统,向下对接大量设备、海量数据,向上支撑金融数字化转型的快速开发与部署,实现数据的可信共享、资源的合理配置、服务的…