主题
12 Go 与 AI:做模型外面那层基础设施
一句话:Go 在 AI 时代的价值不是训练模型,而是承接模型外面那层高并发、可取消、要长期在线的控制面——LLM 网关、MCP 工具服务、Agent 编排、推理路由和可观测性;它换来部署简单和稳定的连接管理,代价是 ML 生态基本不在 Go 这边。
适用 Go 1.22+。MCP Go SDK 已发布 v1.x,具体版本与协议支持以官方仓库为准;项目语言与定位依据官方仓库 README(2026-10 核查)。
为什么需要
AI 系统不是只有模型。请求入口、鉴权、配额、限流、协议转换、工具调用、队列、超时、取消和观测,都是普通后端问题。Python 主导训练和推理生态,Go 则在「连接密集、生命周期长、随时要取消」的层更合适。反过来也要承认:团队是 Python/ML 背景时,硬上 Go 只会增加协作成本,这一篇讲的是位置选择,不是「Go 什么都能做」。
核心机制
适合的位置:连接密集的控制面
| 位置 | Go 承担什么 | 为什么合适 |
|---|---|---|
| LLM 网关/代理 | 鉴权、配额、限流、路由、协议转换、SSE 透传 | 高并发连接、低内存、context 取消、单二进制 |
| MCP server/client | 工具注册、JSON-RPC、stdio/HTTP 传输、执行下游 | 标准库 HTTP/JSON、进程管理、部署简单 |
| Agent/工作流控制面 | 状态、重试、超时、并发编排 | goroutine/channel/context,Temporal 等生态在 Go |
| 推理前路由/队列 | 模型路由、灰度、排队、背压 | 有界队列、低开销并发、可观测 |
| 可观测性/K8s | 采集、sidecar、operator | Kubernetes 本身是 Go,client-go 成熟 |
| CLI/本地工具 | 单文件分发、跨平台 | 静态二进制,不依赖运行时 |
这些位置的共同点是网络和生命周期,不是矩阵运算。goroutine 的初始栈小,适合大量长连接,但每个连接仍有内存和调度成本,必须限流;静态二进制让网关、sidecar、CLI 的镜像和分发都简单;context 把超时和取消做成一等公民,客户端断开能一路传到上游,直接省掉无效的 GPU 计算;net/http 和 encoding/json 足够做网关和 MCP 传输,依赖少、审计面小。
不适合的位置
- 训练/微调:PyTorch、JAX、HuggingFace 的生态和算子库在 Python,Go 没有对应主路径。
- GPU kernel:CUDA、HIP、Triton 和底层 C++,不是 Go 的战场。
- 数据分析/ML 工具链:numpy、pandas、notebook 的交互方式与 Go 不匹配。
- 推理引擎本身:vLLM、SGLang、TensorRT-LLM 的主路径是 Python/C++/CUDA;Go 通常在这些服务前面做代理、路由和队列。
- 需要 Python 能力时:优先子进程、HTTP 或 gRPC 调用;CGO 嵌入解释器可行,但构建、部署和故障排查都会变复杂。
有据可查的 Go 项目
| 项目 | 定位 | Go 的角色 |
|---|---|---|
| Ollama | 本地模型运行与管理 | 主程序 Go;GPU 推理经 CGO 调 C/C++ |
| Weaviate | 向量数据库 | 服务端 Go |
| Kubernetes | 容器编排 | 控制面 Go |
| Temporal | 持久化工作流 | server 与 Go SDK 均为 Go |
| NATS | 消息系统 | server Go |
| MCP Go SDK | MCP client/server | 官方 Go SDK,与 Google 合作维护 |
| one-api / new-api | OpenAI 兼容网关 | Go 后端 |
项目语言和定位按官方仓库 README 核查(2026-10);版本、维护状态和功能会变,引用前再看一眼仓库。
网关的核心:context、Flusher 与背压
- SSE 是长连接,每个事件都要
Flush,中间层不能把整个响应缓冲起来。 - 客户端断开会让
r.Context()取消;把同一个 context 传给上游请求,上游就能停止生成。 - 反向代理和 Nginx 可能缓冲 SSE,要确认 buffering 关闭;HTTP/2 下的 flush 行为以官方文档为准。
- 背压要显式做:上游慢时不要无界开 goroutine 或无限排队,用有界 channel、worker pool、
errgroup.SetLimit。 - 超时分三种:连接、首 token、空闲。只设总超时会误杀长回答,只设首 token 超时又管不住卡住不动的流。
- 优雅停机:先停止接收新请求,等在途请求结束,再取消上游和后台 worker。
MCP 的位置
MCP 用 JSON-RPC 2.0 描述 tools/resources/prompts,传输可以是 stdio 或 HTTP。Go SDK 提供 server/client,工具执行层通常接内部 API、数据库或 Kubernetes。工具调用是特权操作,鉴权、allowlist、超时、审计和沙箱要在服务端做,不能只靠模型自觉。stdio 适合本地工具,HTTP 适合远程服务,取消仍要沿 context 往下传。
最小上手
bash
go run examples/12_ai_sse/main.go
# data: chunk 1
# upstream canceled示例用 httptest 起了一个假推理服务和一个转发代理,不依赖外部服务。关键片段:
go
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
req, _ := http.NewRequestWithContext(r.Context(), http.MethodGet, upstream.URL, nil)
resp, err := http.DefaultClient.Do(req)
if err != nil {
http.Error(w, err.Error(), http.StatusBadGateway)
return
}
defer resp.Body.Close()
w.Header().Set("Content-Type", "text/event-stream")
f := w.(http.Flusher)
br := bufio.NewReader(resp.Body)
for {
line, err := br.ReadString('\n')
if err != nil {
return
}
fmt.Fprint(w, line)
if line == "\n" {
f.Flush()
}
}
}))完整程序见 examples/12_ai_sse/main.go。客户端读到一个事件后调用 cancel(),上游的 r.Context().Done() 随即触发,输出 upstream canceled。
生产动作
- 超时与连接:
http.Server设置ReadHeaderTimeout、IdleTimeout;SSE 的WriteTimeout不能照搬普通接口,否则长回答会被切断。上游 client 单独配Transport的连接池和空闲连接数。 - Flush 与代理:每个 SSE 事件后
Flush;确认 Nginx/网关没有缓冲;返回头写Content-Type: text/event-stream和Cache-Control: no-cache。 - 背压:请求队列、worker 数、每用户并发都要有上限;队列满时快速失败或排队超时,不要无限堆内存。
- 取消传播:所有上游调用都用
NewRequestWithContext;客户端断开、超时、服务停机都要能停掉上游生成。 - 内存与观测:流式转发避免整包缓冲;按容器上限设
GOMEMLIMIT,按延迟目标调GOGC;pprof 只在诊断时开,长期看首 token 延迟、活跃连接、队列深度和上游错误率。 - 优雅停机:
server.Shutdown(ctx)后等待在途请求,再取消根 context;不要直接os.Exit。 - 安全:鉴权、配额、请求体大小、工具 allowlist、审计日志;MCP 工具服务不要把内部管理接口直接暴露给模型。
边界
- Go 不做训练和推理;GPU 计算仍走 CUDA/Python/C++,Go 只做外面那层。
- CGO 接 GPU 或 Python 会带来构建链、镜像体积和跨平台问题,能走 HTTP/gRPC 就不要嵌解释器。
- ML 生态的新模型、新算子通常 Python 先支持,Go SDK 可能滞后;选型时确认所需能力已经可用。
- 团队技能是硬约束:Python-first 团队维护 Go 网关的成本可能高于收益,规模小时直接用现成网关更划算。
- goroutine 不是无限免费;长连接数、每连接内存和 GC 仍要压测,网关的第一瓶颈常是内存和文件描述符。
- MCP 协议和 SDK 仍在演进,版本兼容、传输和安全模型以官方文档为准。
讲清楚
Go 在 AI 系统里的价值是模型外面那层基础设施,不是模型本身。LLM 网关、MCP 工具服务、Agent 控制面、推理路由这些位置的共同点是连接多、生命周期长、要超时和取消,Go 的 goroutine、context、标准库 HTTP 和静态二进制正好合适。它不适合训练、GPU kernel 和 ML 数据分析,这些主路径在 Python/C++/CUDA;Go 通常做推理服务前面的代理,而不是推理引擎。判断要不要用 Go,看团队是否要长期维护高并发控制面、是否需要单二进制部署;如果只是调模型,现成的 Python 工具更省事。
项目语言与定位依据上表官方仓库 README(2026-10 核查);new-api 的仓库归属以官方页面为准。版本、维护状态与协议支持以官方文档为准。 | 适用 Go 1.22+ | 初稿 2026-10