
在实时应用开发中,我们常需要同时提供 HTTP 接口(用于常规请求)和 WebSocket 服务(用于实时双向通信)。那 Go 语言能否高效兼顾这两者?答案是:完全可以,且实现异常简洁。
Go 原生 net/http 包可直接搭建 HTTP 服务,而 WebSocket 可通过成熟的第三方库实现协议升级,两者能共用一个端口、一个服务实例,无需额外部署,天生适配高并发场景。
WebSocket 协议的核心是“基于 HTTP 握手升级”——客户端先发送 HTTP 请求,携带 Upgrade: websocket 等头信息,服务端识别后将连接升级为 WebSocket 长连接,之后双方即可双向收发数据。
Go 中借助 gorilla/websocket 库(Go 生态最主流的 WebSocket 实现,稳定且易用)可快速完成升级,同时不影响原有 HTTP 服务的正常运行。
仅需安装一个第三方库:
go get github.com/gorilla/websocket精简后核心代码(保留双服务核心逻辑,可直接复制运行):
package main
import (
"log"
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}
func handleWS(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { log.Println(err); return }
defer conn.Close()
for {
mt, msg, err := conn.ReadMessage()
if err != nil { break }
log.Printf("recv: %s", msg)
if err := conn.WriteMessage(mt, msg); err != nil { break }
}
}
func handleHTTP(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("HTTP正常 | WebSocket: ws://localhost:8080/ws"))
}
func main() {
http.HandleFunc("/", handleHTTP)
http.HandleFunc("/ws", handleWS)
log.Fatal(http.ListenAndServe(":8080", nil))
}http://localhost:8080,可看到状态提示。ws://localhost:8080/ws,发送消息即可收到回声响应。Go 的 net/http 服务本质是“请求路由器”,不同路径对应不同处理函数:/ 路径走 HTTP 逻辑,/ws 路径触发 WebSocket 升级,两者共享同一个端口和服务进程,由 Go 原生的协程(Goroutine)高效处理并发连接,性能拉满。
CheckOrigin: return true 允许所有跨域请求,生产环境需替换为具体的域名校验逻辑(如判断 r.Header.Get("Origin") 是否在白名单内)。gobwas/ws 库(内存占用更低,支持百万级连接),但 gorilla/websocket 足够覆盖绝大多数中小规模场景。Go 凭借原生 net/http 包的灵活性和第三方 WebSocket 库的成熟度,能轻松同时提供 HTTP 和 WebSocket 服务,代码简洁、并发能力强,非常适合开发实时聊天、监控面板、推送服务等场景。