Go 能同时提供 HTTP 和 WebSocket 服务吗?可以,而且实现很直接

方予
方予
发布时间:2026-08-25| 155人浏览过
原创

前言

很多实时业务都会同时需要 HTTP 接口和 WebSocket 长连接,但不少开发者一开始会以为这意味着两套服务、两个端口甚至两份部署。实际上在 Go 里,借助 `net/http` 的路由能力和 WebSocket 的 HTTP 升级机制,这两类请求可以自然地跑在同一个服务实例中,下面就用最小示例和生产注意点把这件事讲清楚。

很多人在做实时功能时都会碰到同一个问题:普通接口要走 HTTP,消息推送或双向通信又要靠 WebSocket,这两套能力能不能放进同一个 Go 服务里一起跑?答案是可以,而且实现方式比不少人想象得更直接。

这篇文章就用一个最小示例把思路拆开:先说明 Go 为什么能同时处理两种请求,再给出可直接运行的代码,最后补上上线前需要注意的几个关键点,方便你判断它是否适合自己的业务场景。

Go 为什么能同时跑 HTTP 和 WebSocket

Go 可以同时提供 HTTP 和 WebSocket 服务,核心不在于启动两套服务器,而在于 WebSocket 本身就是从 HTTP 请求升级而来。

客户端发起连接时,最开始仍然是一个 HTTP 请求,只是会额外携带 Upgrade: websocket 等请求头。服务端识别到这是 WebSocket 握手后,把这条连接升级为长连接;升级完成后,后续通信就不再按普通 HTTP 的请求-响应模式处理,而是进入持续的双向收发。

这也是为什么在 Go 里可以把两种能力放在同一个 net/http 服务中:普通路径继续按 HTTP 处理,指定路径则执行 WebSocket 升级逻辑。它们共用一个端口、一个进程,部署上不需要额外拆分。

最小可运行示例:一个端口同时提供两种服务

安装依赖

示例只需要一个常用库:

用暖色专栏版式展示 Go 服务如何通过不同路由同时处理 HTTP 请求和 WebSocket 升级请求
同端口双路由示意同一个 `:8080` 端口下,普通请求和 WebSocket 升级请求进入不同处理函数。
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))
}

这段代码实际做了什么

代码结构很简单,但把关键路径都覆盖到了。

handleHTTP 负责普通 HTTP 请求,访问根路径 / 时,服务端返回一个状态说明,证明 HTTP 接口可正常工作。

handleWS 负责 WebSocket 请求,访问 /ws 时,通过 upgrader.Upgrade(w, r, nil) 把当前 HTTP 请求升级成 WebSocket 连接。升级成功后,代码进入一个循环:先读取客户端消息,再把原消息写回去,也就是常见的 echo 回声示例。

而在 main() 中,真正启动的仍然只有一个服务:

log.Fatal(http.ListenAndServe(":8080", nil))

也就是说,HTTP 和 WebSocket 并不是两个独立监听器,而是由同一个监听端口 :8080 对外提供服务,再根据不同路径分发到对应处理函数。

怎么验证它确实同时生效

验证 HTTP

启动程序后,浏览器访问 http://localhost:8080,如果页面能返回状态提示,说明普通 HTTP 路由已经正常工作。

验证 WebSocket

接着再用支持 WebSocket 的测试工具连接 ws://localhost:8080/ws。连上之后发送任意消息,如果服务端把同样的内容回传回来,就说明升级和双向通信链路都已经打通。

这个测试结果有一个直接意义:同一个 Go 进程、同一个端口,可以同时接住浏览器的普通 HTTP 访问,也可以接住 WebSocket 长连接请求。

它为什么能成立:路由分发加上 Goroutine 并发

从实现上看,Go 的 net/http 更像一个请求入口和路由分发器。

在这个例子里:

  • / 走普通 HTTP 逻辑;
  • /ws 走 WebSocket 升级逻辑。

两条路径虽然处理方式不同,但都挂在同一个 HTTP 服务下,因此天然可以共存。

并发方面,Go 的运行时会通过 Goroutine 高效处理大量连接。普通请求来了就进入 HTTP handler,WebSocket 连接建立后则由对应处理逻辑持续收发消息。对于聊天、实时看板、状态推送这类场景,这种模型非常顺手:入口统一,代码不重,扩展也方便。

上生产前,至少要补齐这 3 件事

1. 不要直接保留全开放跨域

示例里这一行:

用便签和卡片展示 Go WebSocket 示例上线前需要补齐的三个生产要点:来源校验、连接管理和库选择
生产环境补齐项示例能跑通只是第一步,真正上线时更重要的是把来源校验、连接生命周期和库选型补完整。
CheckOrigin: func(r *http.Request) bool { return true }

只是为了让本地演示尽快跑通。它表示允许所有来源发起 WebSocket 升级请求,这在生产环境里风险很高。

更稳妥的做法,是检查 r.Header.Get("Origin") 是否命中允许列表,只放行明确受信任的域名。

2. 连接管理不能只靠示例循环

示例中的循环足够说明读写流程,但真正上线时,通常还需要维护连接池,例如用 map 保存活跃连接,并处理以下问题:

  • 断线后的清理;
  • 客户端重连;
  • 心跳检测;
  • 无效连接的资源回收。

否则连接一多,很容易出现资源长期占用、状态不一致或广播失败等问题。

3. 库选择要看场景规模

文中的 gorilla/websocket 依然是 Go 生态里非常主流、易用且稳定的方案,对大多数中小规模场景已经足够。

如果业务目标是更高密度的连接数,或者对内存占用更敏感,也可以考虑 gobwas/ws。它的特点是更偏底层、内存开销更低,适合高并发压力更大的场景,甚至可用于百万级连接方向的优化。但从开发效率和可维护性来看,很多项目先用 gorilla/websocket 起步会更实际。

结论:Go 不只能做,而且很适合这么做

回到最初的问题,Go 不仅能同时提供 HTTP 和 WebSocket 服务,而且实现路径非常自然:普通请求交给 net/http,需要实时双向通信的请求则在特定路由上升级为 WebSocket。

从开发角度看,它的优势是结构简单、部署集中、并发处理能力强;从业务角度看,聊天、监控面板、通知推送、协作编辑这类需要实时性的系统,都可以直接沿着这个模式扩展。对于想在一个服务里同时兼顾常规接口和实时通信的项目,这是一种足够轻量、也足够实用的方案。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。