跳到正文

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、operatorKubernetes 本身是 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 SDKMCP client/server官方 Go SDK,与 Google 合作维护
one-api / new-apiOpenAI 兼容网关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

把一门技术讲透到既懂也会用