# 快速开始
最近几年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吧,希望大家多提意见,一起来完善,谢谢~
有疑问加站长微信联系(非本文作者)