deepseek官方不提供原生websocket接口,所有“go+websocket+deepseek”方案本质是go服务端用http.client调用其rest流式api(/v1/chat/completions?stream=true),再通过websocket将sse风格响应转发给前端;硬连ws://api.deepseek.com必然失败,因其仅开放https rest端点,未监听任何websocket协议。
deepseek 官方不提供原生 websocket 接口,所有“go + websocket + deepseek”方案,本质都是在 go 服务端用 http.client 调用其 rest /v1/chat/completions 接口(启用 stream=true),再通过 websocket 将流式响应转发给前端。硬连 ws://api.deepseek.com 必然失败——它压根没开这个服务。
为什么不能直接 WebSocket 连接 DeepSeek
常见错误现象:Connection refused、404 Not Found、浏览器报 Failed to construct 'WebSocket'。
-
api.deepseek.com只暴露 HTTPS REST 端点,ws://和wss://均无监听 - 所谓“DeepSeek WebSocket SDK”不存在;社区示例里出现的
ws://地址,背后全是自建中转层(如 FastAPI/Go 服务) - 官方文档、OpenAPI Spec、API 控制台均未列出任何 WebSocket 路径
Go 服务端如何正确转发 stream 响应
关键不是“连 DeepSeek 的 WebSocket”,而是“用 Go 把 DeepSeek 的 SSE 风格流,桥接到你自己的 WebSocket 连接”。需注意三点:
- DeepSeek 的
stream=true返回是 chunked HTTP body,每块是 JSON 行(非标准 SSE),含data:前缀、空行、可能的首尾空格 ——http.Client必须用response.Body手动读取,不能依赖json.Decoder直接 decode 整体响应 - Go WebSocket 服务端推荐用
github.com/gorilla/websocket,它支持并发安全的WriteMessage,且能处理连接中断后自动清理 - 必须逐 chunk 解析:跳过空行 → 去掉
data:→json.Unmarshal提取choices[0].delta.content→ 再通过 WebSocket 发给前端
示例核心逻辑片段:
统一LLM网关 - 一个API对接70+AI模型,使用单一API密钥即可调用GPT、Claude、Gemini、Qwen、Deepseek、Grok等主流模型。
for {
buf := make([]byte, 1024)
n, err := resp.Body.Read(buf)
if n > 0 {
lines := bytes.Split(bytes.TrimSpace(buf[:n]), []byte("\n"))
for _, line := range lines {
if bytes.HasPrefix(line, []byte("data:")) {
data := bytes.TrimSpace(bytes.TrimPrefix(line, []byte("data:")))
if len(data) == 0 || bytes.Equal(data, []byte("[DONE]")) {
continue
}
var chunk struct {
Choices []struct {
Delta struct { Content string } `json:"delta"`
} `json:"choices"`
}
if json.Unmarshal(data, &chunk) == nil && len(chunk.Choices) > 0 {
if content := chunk.Choices[0].Delta.Content; content != "" {
conn.WriteMessage(websocket.TextMessage, []byte(content))
}
}
}
}
}
if err == io.EOF {
break
}
if err != nil {
break
}
}
前端 WebSocket 连接的是你自己的 Go 服务,不是 DeepSeek
前端代码里的 new WebSocket("ws://localhost:8080/ws"),目标地址必须是你用 gorilla/websocket 启起来的 Go 服务(比如 /ws 路由),而不是任何 DeepSeek 域名。
- 你的 Go 服务负责:接收前端消息 → 组装
messages数组 → 调用api.deepseek.com/v1/chat/completions?stream=true→ 流式解析 → 用 WebSocket 推送内容 - 不要在前端尝试绕过你的服务直连 DeepSeek —— 会暴露
Authorization头,且跨域被拦死 - 若需多用户隔离,需在 Go 服务端用
map[string]*websocket.Conn绑定 session ID,避免消息错发
真正卡住人的地方,从来不是写几行 upgrader.Upgrade,而是误以为 DeepSeek 支持 WebSocket 协议本身。所有流式交互的“实时感”,都来自你本地 Go 服务对 HTTP 流的及时捕获与低延迟转发——这中间的 chunk 解析容错、连接异常重试、并发写保护,才是实际要花时间调的地方。










