gin使用websocket實(shí)現(xiàn)數(shù)據(jù)實(shí)時(shí)推送
業(yè)務(wù)場(chǎng)景
今天給自己的項(xiàng)目加了幾個(gè)echarts圖表,主要用以顯示我的幾個(gè)系統(tǒng)的近一周訪問(wèn)量,大概是這個(gè)樣子

三個(gè)圖標(biāo)分別是:我的簡(jiǎn)歷訪問(wèn)量,我的音樂(lè)訪問(wèn)量,簡(jiǎn)歷和音樂(lè)訪問(wèn)量對(duì)比
1.數(shù)據(jù)采集
這個(gè)訪問(wèn)信息的采集是在我的簡(jiǎn)歷和我的音樂(lè)頁(yè)面提交信息,也就是個(gè)很簡(jiǎn)單的接口,提交用戶訪問(wèn)該頁(yè)面的時(shí)間和頁(yè)面類型(簡(jiǎn)歷頁(yè)面或者是音樂(lè)頁(yè)面)
2,數(shù)據(jù)整理
把近一周時(shí)間內(nèi)每天的訪問(wèn)量整理出來(lái)返回給前端系統(tǒng)
// 獲取我的音樂(lè)本周訪問(wèn)量
func (this Personal) GetMusicData(ctx *gin.Context) {
now := time.Now()
year, month, day := now.Date()
// 今天的時(shí)間
today := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
//今天的時(shí)間-1
t1 := today.AddDate(0, 0, -1)
//今天的時(shí)間-2
t2 := today.AddDate(0, 0, -2)
//今天的時(shí)間-3
t3 := today.AddDate(0, 0, -3)
//今天的時(shí)間-4
t4 := today.AddDate(0, 0, -4)
//今天的時(shí)間-5
t5 := today.AddDate(0, 0, -5)
//今天的時(shí)間-6
t6 := today.AddDate(0, 0, -6)
tourist1 := []modules.Tourist{}
tourist2 := []modules.Tourist{}
tourist3 := []modules.Tourist{}
tourist4 := []modules.Tourist{}
tourist5 := []modules.Tourist{}
tourist6 := []modules.Tourist{}
tourist7 := []modules.Tourist{}
err := modules.DB.Where("scene LIKE ? AND add_time > ?", "%music%", today).Find(&tourist1).Error
err2 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t1, today).Find(&tourist2).Error
err3 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t2, t1).Find(&tourist3).Error
err4 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t3, t2).Find(&tourist4).Error
err5 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t4, t3).Find(&tourist4).Error
err6 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t5, t4).Find(&tourist4).Error
err7 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t6, t5).Find(&tourist4).Error
if err != nil || err2 != nil || err3 != nil || err4 != nil || err5 != nil || err6 != nil || err7 != nil {
ctx.JSON(400, gin.H{
"message": "獲取失敗",
})
} else {
arr := []int{len(tourist7), len(tourist6), len(tourist5), len(tourist4), len(tourist3), len(tourist2), len(tourist1)}
ctx.JSON(200, gin.H{
"message": "獲取成功",
"data": arr,
})
}
}
這是整理音樂(lè)頁(yè)面訪問(wèn)量的函數(shù),簡(jiǎn)歷頁(yè)面同理
3,前端獲取到數(shù)據(jù)后把數(shù)據(jù)綁定給echarts圖標(biāo)
... ... 此處省略前端代碼若干行
4,重點(diǎn)部分:使用websocket和服務(wù)端生成長(zhǎng)鏈接,訪問(wèn)量變化了實(shí)時(shí)通知前端獲取最新數(shù)據(jù)
后端部分"github.com/gorilla/websocket"
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
//這里聲明一個(gè)鏈接池
var conns []*websocket.Conn
func (this UserController) WS(w http.ResponseWriter, r *http.Request) {
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
println("upgrade錯(cuò)誤:", err)
return
}
defer c.Close()
//把所有鏈接存在鏈接池里
conns = append(conns, c)
for {
_, _, err := c.ReadMessage()
if err != nil {
println("read:", err)
break
}
}
}
在數(shù)據(jù)采集到函數(shù)里,當(dāng)收到有人訪問(wèn)那兩個(gè)頁(yè)面,把鏈接池里的鏈接都通知一遍
func (this UserController) AddTourist(ctx *gin.Context) {
scene := ctx.Request.FormValue("scene")
message := ctx.Request.FormValue("message")
time := time.Now().UTC()
tourist := &modules.Tourist{
Scene: scene,
Message: message,
AddTime: time,
}
err := modules.DB.Model(&modules.Tourist{}).Create(&tourist).Error
if err != nil {
ctx.JSON(400, gin.H{
"message": "新增瀏覽用戶信息失敗",
})
} else {
//這里是重點(diǎn),循環(huán)鏈接池,廣播消息,消息類型隨便定,只要你前端知道就行,我這里通知一個(gè)數(shù)字1
for i := range conns {
if index := strings.Index(scene, "jianli"); index != -1 {
conns[i].WriteMessage(websocket.TextMessage, []byte("jianli"))
} else if index := strings.Index(scene, "music"); index != -1 {
conns[i].WriteMessage(websocket.TextMessage, []byte("music"))
}
}
ctx.JSON(200, gin.H{
"message": "新增瀏覽用戶信息成功!",
})
}
}
然后是管理系統(tǒng)收到推送的消息,重新刷新數(shù)據(jù),這樣就實(shí)現(xiàn)了數(shù)據(jù)隨訪問(wèn)量實(shí)時(shí)變化的功能
const websocket=new WebSocket("ws://xxx.xxx.xxx.xxx:8088/ws")
websocket.onopen=(evt)=>{
console.log("鏈接成功")
}
websocket.onmessage=(evt)=>{
//收到后端推送的消息,刷新對(duì)應(yīng)數(shù)據(jù)
if(evt.data=="jianli"){
refreshChartJL()
}else if(evt.data=="music"){
refreshChartMusic()
}
}
websocket.onclose=()=>{
console.log("鏈接關(guān)閉")
}
const getAllData=()=>{
...
...
...
}
總結(jié):這個(gè)功能實(shí)現(xiàn)下來(lái),也并不難,但一定要?jiǎng)邮謱?shí)現(xiàn)一下,如果你有啥疑問(wèn),可以留言,我每天都能看到
到此這篇關(guān)于gin使用websocket實(shí)現(xiàn)數(shù)據(jù)實(shí)時(shí)推送的文章就介紹到這了,更多相關(guān)gin websocket數(shù)據(jù)實(shí)時(shí)推送內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何用go操作iptables和ipset設(shè)置黑白名單
這篇文章主要介紹了如何用go操作iptables和ipset設(shè)置黑白名單問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-06-06
Go語(yǔ)言的GoRoot和GoPath的區(qū)別小結(jié)
Go語(yǔ)言通過(guò)GOROOT和GOPATH配置開(kāi)發(fā)環(huán)境,GOROOT指定Go安裝目錄,GOPATH傳統(tǒng)模式下定義工作區(qū),存放項(xiàng)目代碼和依賴,下面就來(lái)詳細(xì)的介紹一下兩者的區(qū)別,感興趣的可以了解一下2025-10-10
解決golang結(jié)構(gòu)體tag編譯錯(cuò)誤的問(wèn)題
這篇文章主要介紹了解決golang結(jié)構(gòu)體tag編譯錯(cuò)誤的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05
解決Golang中ResponseWriter的一個(gè)坑
這篇文章主要介紹了解決Golang中ResponseWriter的一個(gè)坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04
Go1.16新特性embed打包靜態(tài)資源文件實(shí)現(xiàn)
這篇文章主要為大家介紹了Go?1.16新特性embed打包靜態(tài)資源文件的實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Go語(yǔ)言中轉(zhuǎn)換JSON數(shù)據(jù)簡(jiǎn)單例子
這篇文章主要介紹了Go語(yǔ)言中轉(zhuǎn)換JSON數(shù)據(jù)簡(jiǎn)單例子,本文先定義了一個(gè)結(jié)構(gòu)體,然后把JSON綁定到結(jié)構(gòu)體上實(shí)現(xiàn)讀取,需要的朋友可以參考下2014-10-10
使用Go開(kāi)發(fā)一個(gè)文件同步小工具(附源碼)
這篇文章主要為大家詳細(xì)介紹了如何使用Go開(kāi)發(fā)一個(gè)文件同步小工具并附上源碼,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-11-11

