DeepSeek 官方 API 不支持 WebSocket,仅提供 RESTful SSE 流式接口;所谓“WebSocket 连接 DeepSeek”实为对接 SiliconFlow 等第三方代理或自建桥接服务。

Go 无法直接用 gorilla/websocket 连接 DeepSeek 官方 API 实现 WebSocket 流式交互——因为官方根本没有开放 wss://api.deepseek.com 这类 WebSocket 端点。你实际连上的,要么是 SiliconFlow 等第三方兼容代理(如 wss://cloud.siliconflow.cn/v1/chat/completions),要么是自建的 vLLM/Ollama + OpenAI 协议桥接服务。所谓“DeepSeek WebSocket”,本质是协议伪装,不是原生支持。
为什么 websocket.Dial 连 wss://api.deepseek.com 必然失败
DeepSeek 官方 API(截至 2026 年 5 月)只提供 RESTful 接口 POST /v1/chat/completions,且仅支持 stream=true 时返回 text/event-stream 格式(SSE)。它不响应 Upgrade: websocket 请求头,也不在 OpenAPI spec 中声明任何 WebSocket 路径。
- 常见错误现象:
404或426 Upgrade Required但无有效Sec-WebSocket-Accept响应头 - 即使
gorilla/websocket.Dial表面成功,后续WriteMessage会立刻触发close,日志常报invalid request format - 误把 SSE 的
data: {...}分块当成 WebSocket 文本帧解析,导致 JSON 解析 panic
Go 中真正可行的流式方案:REST + text/event-stream
优先走标准 HTTP 流式。Go 标准库 net/http 开箱即用,无需额外依赖,与 DeepSeek 官方行为 100% 对齐,天然支持超时、重试、代理穿透。
- 请求头必须设
Accept: text/event-stream和Content-Type: application/json - Body 中
"stream": true是硬性要求,缺则返回完整响应而非流式 - 响应体是逐行
data: {json}块,需手动按行读取、剥离data:前缀、再json.Unmarshal - 注意处理空行分隔、
event:/id:等可选字段,DeepSeek 当前只用data:
真要用 WebSocket?先确认你连的是谁
如果你坚持用 WebSocket,必须明确终点不是 DeepSeek 官方,而是某个兼容 OpenAI 协议的代理服务。典型目标地址包括:
-
wss://cloud.siliconflow.cn/v1/chat/completions(SiliconFlow 公共端点) -
wss://your-domain.com/v1/chat/completions(你自建的 DS2API 或 vLLM-Ollama 桥接服务)
这类服务通常要求:
- 连接时 URL 带
api_key查询参数(如?api_key=sk-xxx) - 发送消息为标准 OpenAI 格式 JSON,含
model、messages、stream: true - 接收帧可能是文本或二进制,需按代理文档约定解析(例如 SiliconFlow 返回纯 JSON 字符串,DS2API 则完全复刻 OpenAI 流式 chunk 结构)
- 必须自行实现 ping/pong 心跳、断线重连、连接池管理——
gorilla/websocket不自动帮你做这些
容易被忽略的关键点
很多人卡在流式响应的边界处理上:SSE 的 data: 行末可能带换行符,JSON 解析前没 strings.TrimSpace 就 panic;WebSocket 场景下,代理返回的 delta.content 可能为空字符串(比如遇到 role 或 finish_reason),不判空就 nil pointer dereference;还有更隐蔽的——DeepSeek 官方接口对请求头 Authorization 的值格式极其敏感,必须是 Bearer sk-xxx,少个空格或大小写错都会静默退化为非流式响应。











