十行代码增强Gin处理Websocket的能力

ideaa · · 462 次点击 · 开始浏览    置顶

# 快速开始 最近几年Golang写的比较多,HTTP使用Gin,简单高效。今天我们来增强Gin处理Websocket的能力,先上代码: ```go package main import ( "net/http" "time" "github.com/gin-gonic/gin" "github.com/wonli/aqi" "github.com/wonli/aqi/ws" ) func main() { app := aqi.Init( aqi.ConfigFile("config.yaml"), aqi.HttpServer("Aqi", "port"), ) engine := gin.Default() // Gin路由 engine.GET("/", func(c *gin.Context) { c.String(http.StatusOK, "Hi aqi!") }) // Websocket入口 engine.GET("/ws", func(c *gin.Context) { ws.HttpHandler(c.Writer, c.Request) }) // Websoket路由注册 wsr := ws.NewRouter() wsr.Add("hi", func(a *ws.Context) { a.Send(ws.H{ "hi": time.Now(), }) }) app.WithHttpServer(engine) app.Start() } ``` 使用方法很简单,先初始化路由`ws.NewRouter()`,然后使用Add方法注册, 最后将`engine`作为参数传给`app.WithHttpServer(engine)`。这样在愉快的使用gin处理HTTP的时候,也可以愉快的处理Websocket了。 ```go wsr := ws.NewRouter() wsr.Add("hi", func(a *ws.Context) { a.Send(ws.H{ "hi": time.Now(), }) }) ``` 我们使用wscat来作为websocket客户端,在terminal中新开一个tab,使用 `wscat -c ws://127.0.0.1:2015/ws` 与服务端建立连接后,输入`{"action":"hi"}`后可以看到服务器返回了当前时间. 运行截图如下: ![1.png](https://static.golangjob.cn/240619/da2886a2fc568a73faba63de503ce968.png) # 处理输入参数 我们可以很方便的在业务代码中处理用户输入,接收用户输入的ID再原样返回: ```go wsr.Add("hi", func(a *ws.Context) { id := a.GetInt("id") a.Send(ws.H{ "hi": time.Now(), "id": id, }) }) ``` 我们已经在业务代码中成功接收和处理输入的ID了 ![2.png](https://static.golangjob.cn/240619/fdf4ec022e09afc230293f0b3023457f.png) 在`*ws.Context`中,我们封装了一系列方法来方便的处理输入输出,`Get`开头的系列方法获取指定用户输入的参数,比如ID,Name等。`Binding`开头系列用于将用户输入转换为一个struct,这是最常用的。`Send`开头用于发送数据到客户端,具体请查看代码。 ![3.png](https://static.golangjob.cn/240619/0ab36eb263fa9563b93301e090f45b08.png) # 使用中间件 在`Aqi`中使用中间件跟Gin类似,先注册一个中间件, 在服务panic的时候收集打印日志,并返回错误码: ```go package middlewares import ( "runtime/debug" "github.com/wonli/aqi/logger" "github.com/wonli/aqi/ws" ) func Recovery() ws.HandlerFunc { return func(a *ws.Context) { defer func() { if err := recover(); err != nil { // 获取 panic 发生的堆栈跟踪 stack := debug.Stack() logger.SugarLog.Errorf("Panic happened: %s \n %s\n", err, stack) a.SendCode(30, "服务维护中") a.Abort() } }() a.Next() } } ``` 在业务代码中使用中间件: ```go wsr := ws.NewRouter() wsr.Use(middlewares.Recovery()).Add("hi", func(a *ws.Context) { panic("hi") }) ``` 当然也可以这样: ```go wsr := ws.NewRouter() r1 := wsr.Use(middlewares.Recovery()) { r1.Add("hi", func(a *ws.Context) { panic("hi") }) } ``` 当我们程序panic的时候,不会终止进程,而是返回对应的错误信息给客户端. ![4.png](https://static.golangjob.cn/240619/a6c194af8925d08c49714ea222388ebe.png) 有没有觉得很方便,目前已经开源,感兴趣的小伙伴请点个start吧,希望大家多提意见,一起来完善,谢谢~

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

462 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传