news 2026/4/16 18:15:13

Go语言的WebSocket开发

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Go语言的WebSocket开发

Go语言的WebSocket开发

WebSocket基础

WebSocket是一种在单个TCP连接上进行全双工通信的协议,它允许服务器和客户端之间进行实时数据交换。在Go语言中,WebSocket支持由gorilla/websocket包提供。

基本使用

安装依赖

go get github.com/gorilla/websocket

创建WebSocket服务器

package main import ( "fmt" "net/http" "github.com/gorilla/websocket" ) var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true // 允许所有来源的请求 }, } func wsHandler(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { fmt.Println("Error upgrading to WebSocket:", err) return } defer conn.Close() for { // 读取消息 messageType, message, err := conn.ReadMessage() if err != nil { fmt.Println("Error reading message:", err) break } fmt.Printf("Received message: %s\n", message) // 发送消息 err = conn.WriteMessage(messageType, message) if err != nil { fmt.Println("Error writing message:", err) break } } } func main() { http.HandleFunc("/ws", wsHandler) fmt.Println("WebSocket server starting on port 8080...") http.ListenAndServe(":8080", nil) }

客户端实现

使用JavaScript客户端

<!DOCTYPE html> <html> <head> <title>WebSocket Client</title> </head> <body> <input type="text" id="message" placeholder="Enter message"> <button onclick="sendMessage()">Send</button> <div id="messages"></div> <script> const socket = new WebSocket('ws://localhost:8080/ws'); socket.onopen = function(event) { console.log('Connected to WebSocket server'); }; socket.onmessage = function(event) { const messages = document.getElementById('messages'); messages.innerHTML += '<p>Server: ' + event.data + '</p>'; }; socket.onclose = function(event) { console.log('Disconnected from WebSocket server'); }; socket.onerror = function(error) { console.error('WebSocket error:', error); }; function sendMessage() { const messageInput = document.getElementById('message'); const message = messageInput.value; if (message) { socket.send(message); const messages = document.getElementById('messages'); messages.innerHTML += '<p>Client: ' + message + '</p>'; messageInput.value = ''; } } </script> </body> </html>

高级功能

消息类型

WebSocket支持三种消息类型:

  • TextMessage (1): 文本消息
  • BinaryMessage (2): 二进制消息
  • CloseMessage (8): 关闭连接消息
// 发送文本消息 conn.WriteMessage(websocket.TextMessage, []byte("Hello, WebSocket!")) // 发送二进制消息 conn.WriteMessage(websocket.BinaryMessage, []byte{1, 2, 3, 4, 5})

心跳检测

package main import ( "fmt" "net/http" "time" "github.com/gorilla/websocket" ) var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } func wsHandler(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { fmt.Println("Error upgrading to WebSocket:", err) return } defer conn.Close() // 设置心跳检测 conn.SetReadDeadline(time.Now().Add(60 * time.Second)) conn.SetPongHandler(func(string) error { conn.SetReadDeadline(time.Now().Add(60 * time.Second)) return nil }) // 启动心跳发送协程 go func() { ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() for { select { case <-ticker.C: err := conn.WriteMessage(websocket.PingMessage, nil) if err != nil { return } } } }() // 处理消息 for { messageType, message, err := conn.ReadMessage() if err != nil { if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) { fmt.Printf("Error: %v\n", err) } break } fmt.Printf("Received message: %s\n", message) err = conn.WriteMessage(messageType, message) if err != nil { fmt.Println("Error writing message:", err) break } } } func main() { http.HandleFunc("/ws", wsHandler) fmt.Println("WebSocket server starting on port 8080...") http.ListenAndServe(":8080", nil) }

示例:实时聊天应用

服务器端

package main import ( "fmt" "net/http" "sync" "github.com/gorilla/websocket" ) var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } var ( clients = make(map[*websocket.Conn]bool) broadcast = make(chan []byte) clientsMu sync.Mutex ) func wsHandler(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { fmt.Println("Error upgrading to WebSocket:", err) return } defer conn.Close() // 添加客户端 clientsMu.Lock() clients[conn] = true clientsMu.Unlock() // 处理消息 for { _, message, err := conn.ReadMessage() if err != nil { clientsMu.Lock() delete(clients, conn) clientsMu.Unlock() break } broadcast <- message } } func broadcastMessages() { for { message := <-broadcast clientsMu.Lock() for client := range clients { err := client.WriteMessage(websocket.TextMessage, message) if err != nil { client.Close() delete(clients, client) } } clientsMu.Unlock() } } func main() { // 启动广播协程 go broadcastMessages() http.HandleFunc("/ws", wsHandler) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "index.html") }) fmt.Println("Chat server starting on port 8080...") http.ListenAndServe(":8080", nil) }

客户端

<!DOCTYPE html> <html> <head> <title>Real-time Chat</title> <style> #messages { height: 300px; overflow-y: scroll; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; } </style> </head> <body> <div id="messages"></div> <input type="text" id="message" placeholder="Enter message" style="width: 80%;"> <button onclick="sendMessage()">Send</button> <script> const socket = new WebSocket('ws://localhost:8080/ws'); socket.onopen = function(event) { console.log('Connected to chat server'); }; socket.onmessage = function(event) { const messages = document.getElementById('messages'); messages.innerHTML += '<p>' + event.data + '</p>'; messages.scrollTop = messages.scrollHeight; }; socket.onclose = function(event) { console.log('Disconnected from chat server'); }; socket.onerror = function(error) { console.error('WebSocket error:', error); }; function sendMessage() { const messageInput = document.getElementById('message'); const message = messageInput.value; if (message) { socket.send(message); messageInput.value = ''; } } // 按Enter键发送消息 document.getElementById('message').addEventListener('keypress', function(e) { if (e.key === 'Enter') { sendMessage(); } }); </script> </body> </html>

性能优化

  • 使用连接池管理WebSocket连接
  • 实现消息批量发送
  • 使用缓冲区减少内存分配
  • 合理设置心跳检测间隔
  • 限制单个连接的消息频率

总结

Go语言的gorilla/websocket包提供了强大的WebSocket支持,通过合理使用这些功能,可以构建实时聊天、实时数据更新等应用。WebSocket的全双工通信特性使其在需要实时数据交换的场景中非常有用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 18:14:16

MMPose实战:从算法原理到多场景人体关键点识别应用

1. MMPose入门&#xff1a;人体姿态估计的基石 第一次接触MMPose时&#xff0c;我被这个开源库的全面性震撼到了。作为PyTorch生态中的姿态估计专用工具包&#xff0c;它几乎囊括了从2D到3D、从单人到多人的所有主流算法。记得去年做一个健身动作识别项目时&#xff0c;我尝试…

作者头像 李华
网站建设 2026/4/16 18:11:12

国民技术 N32G452CCL7 LQFP-48 单片机

特性32位ARM Cortex-M4内核 FPU&#xff0c;单周期硬件乘除法指令&#xff0c;支持DSP指令和MPU内置8KB指令Cache缓存&#xff0c;支持Flash加速单元执行程序0等待最高主频144MHz&#xff0c;180DMIPS高达512KByte片内Flash&#xff0c;支持加密存储、多用户分区管理及数据保护…

作者头像 李华
网站建设 2026/4/16 18:10:40

高端商用投影仪功率链路优化:基于高效供电、精准散热与静音风扇驱动的MOSFET精准选型方案

前言&#xff1a;构筑光影引擎的“能量基石”——论功率器件选型的系统思维在追求极致亮度、对比度与可靠性的高端商用投影仪领域&#xff0c;每一缕精准投射的光线背后&#xff0c;都是一场对电能高效、稳定、静默转换的严苛考验。其核心性能——高亮度输出的稳定性、长久运行…

作者头像 李华