第2章 别急,先把刀磨快
第1章讲完了AI Agent是什么、为什么Go能做。这一章不急着写Agent代码——我见过太多人,兴致勃勃想写AI,结果环境装了三天还没跑起来。学AI的第一步,不是AI,是把工具准备好。 Go的环境比Python省心太多,但也有一些坑要绕开。
2.1 朋友问我Go怎么搞AI
2.1.1 你不是不会Go,你是不知道从哪开始
去年有个朋友来找我:"我看完你的文章了,Go确实能做AI。但第一步干什么?装什么?用哪个框架?"
我说你先装个Go。
他愣了两秒:"……Go我早装了,天天写。我是问AI怎么搞。"
这个问题很典型。很多人觉得"我会Go"和"我会用Go写AI"是两回事——其实不是。Go写AI Agent和你写HTTP服务,用到的工具、环境、编辑器,90%是一样的。 唯一的区别是多了一个Eino框架。
2.1.2 安装Go(一次搞定,一劳永逸)
去 go.dev/dl 下载安装包。相比Python,Go的安装简单太多了——没有系统自带版本冲突、没有2 vs 3的纠结、一个安装包搞定一切。
版本建议:
- Go 1.21 以上——本书用的泛型、
slices/maps标准库包需要这个版本 - Go 1.22 以上更推荐——
for range循环的变量语义改进,少踩坑 - 当前最新稳定版也行——Go 的向后兼容做得很好,很少出现"新版跑不了老代码"
安装完验证:
bash
go version
# go version go1.22.0 darwin/arm64macOS 用户:
bash
# 用 Homebrew 装
brew install go@1.22
# 或者直接下载 pkg 安装包双击安装Linux 用户:
bash
# 下载后解压到 /usr/local
tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin # 加到 ~/.bashrc 或 ~/.zshrcWindows 用户:下载 .msi 安装包,一路下一步就行。
装完别忘了设置 GOPATH(Go 1.16 之后 go modules 模式已经不强制要求了,但有些工具还会用到):
bash
go env GOPATH
# /Users/你的用户名/go2.1.3 Go Modules:你第一个AI项目的依赖管理
Python 开发者要操心 venv + pip + requirements.txt。Go 开发者的依赖管理只有一个东西:Go Modules。
bash
# 新建项目
mkdir my-agent && cd my-agent
# 初始化模块
go mod init github.com/你的用户名/my-agent这一行命令做了三件事:
- 创建
go.mod——记录你的项目名和 Go 版本 - 以后
go get的依赖会自动写入go.mod go.sum会自动生成——锁定每个依赖的精确版本和哈希值
对比 Python 的依赖管理:
| Python | Go | |
|---|---|---|
| 初始化项目 | python -m venv + pip install | go mod init |
| 添加依赖 | pip install langchain==0.3.30 | go get github.com/cloudwego/eino@v0.3.0 |
| 锁定版本 | requirements.txt(手动) | go.sum(自动) |
| 安装所有依赖 | pip install -r requirements.txt | go mod download(通常不需要,go build 自动处理) |
| 隔离环境 | venv 给每个项目一个独立房间 | Go Modules 本身就能做到 |
可以理解为:Go Modules 把 venv + pip + requirements.txt 三件事合成了一件。 不需要激活环境、不需要 freeze、不需要担心装到全局——因为 Go 根本就没有"全局包"这个概念。
2.1.4 一个标准项目骨架
装好Go、初始化模块之后,我习惯按这个结构组织项目:
my-agent-project/
├── .env # API Key 等敏感信息(不要提交到 git)
├── .gitignore # 告诉 git 哪些文件不用管
├── go.mod # 模块定义和依赖(自动生成)
├── go.sum # 依赖版本锁定(自动生成)
├── main.go # 入口文件
├── agent/ # Agent 核心逻辑
│ ├── agent.go
│ ├── tools.go
│ └── memory.go
├── config/ # 配置管理
│ └── config.go
├── data/ # 数据文件
└── README.md有几个值得注意的点:
.env存敏感信息——API Key 放这里,代码里用os.Getenv()读,别硬编码go.mod和go.sum必须提交到 git——和 Python 不同,Go 的依赖文件是项目的一部分,别人 clone 下来go build就能跑- Go 不需要
__init__文件——目录名就是包名,省心
2.2 依赖地狱?Go不存在
2.2.1 go get:唯一需要记住的命令
Go 的包管理简单到只需要记一条命令:
bash
# 安装依赖
go get github.com/cloudwego/eino@v0.3.0
# 更新到最新
go get -u github.com/cloudwego/eino
# 清理不再使用的依赖
go mod tidy为什么加版本号? 和 Python 一样,你的代码基于特定版本写出来的。半年后换台电脑,不加版本号可能拉到不兼容的新版。
但和 Python 不同——Go 会在编译期就发现类型不兼容。Python 要等到运行时才炸,Go 在 go build 的时候就告诉你了。
2.2.2 go.sum:自动挡的版本锁定
Python 开发者最怕的场景:
ERROR: langchain 0.3.30 requires pydantic>=2.0, but you have pydantic 1.10.0Go 的解决方式是完全自动的——go.sum 文件记录了每个依赖的精确版本和哈希值。你不需要手动 freeze,不需要写 requirements.txt,go.sum 自动帮你管好一切。
即使真遇到了冲突(A 依赖 C v1.0,B 依赖 C v2.0),Go 的**最小版本选择(MVS)**算法会自动挑一个兼容版本。这比 Python 的 pip 回溯算法稳定得多。
2.2.3 真遇到冲突怎么办
虽然少,但不是不可能遇到。如果你遇到了——
bash
# 查看为什么某个包被引入了
go mod why github.com/某个冲突的包
# 最坏情况:清理缓存,重新拉
go clean -modcache
go mod tidy一条经验法则:在 Go 的世界里,依赖管理的问题 90% 用 go mod tidy 能解决。不像 Python,一个依赖冲突可能让你调试一下午。
2.3 工具选对了,写代码是享受
2.3.1 VSCode(推荐)
适合:写项目代码、日常开发
优点:
- 免费、轻量、启动快
- Copilot 插件——AI 帮你写代码
- 终端内置——
go build、go run不用切窗口
必装插件:
- Go(官方):代码提示、格式化、调试、测试,全包了
- Error Lens:错误信息直接显示在行尾,不用鼠标悬停
装完 Go 插件后,它会自动提示你安装 gopls(Go 语言服务器)和 dlv(调试器),一路确认就行。
2.3.2 GoLand
适合:大型项目、团队协作
优点:
- JetBrains 出品,Go 开发的全功能 IDE
- 重构工具强大——重命名、提取函数、改签名,比 VSCode 顺手
- 数据库工具、HTTP 客户端、Docker 管理——全内置
缺点:
- 付费(有免费试用期)
- 比 VSCode 重,启动慢
如果你来自 Java 背景(IntelliJ IDEA),GoLand 的操作逻辑零学习成本。
2.3.3 Go Playground
适合:快速试一段代码、分享代码片段
浏览器打开 go.dev/play,写代码直接跑。不需要装任何东西。
局限:不能引入第三方包(Eino 没法在上面跑),网络请求受限。
本书的使用建议:学语法、做小实验用 Playground。正经写 Agent 代码,用 VSCode 或 GoLand。
2.4 Eino全家桶初体验
装完环境,先看一眼你接下来会频繁打交道的几个组件。不用现在就装,心里有个地图就行。
2.4.1 Eino:Go的AI Agent框架
Eino 是字节跳动 2024 年开源的 Go AI Agent 框架。对应关系可以理解为:
| Python 生态 | Go 生态(Eino) |
|---|---|
| LangChain | Eino(组装 Agent 的积木箱) |
| LangGraph | Eino 的 Graph 模块(分支、循环、状态管理) |
| ChromaDB / FAISS | Eino 的 Retriever 接口(对接任意向量数据库) |
Eino 最舒服的一点:它的 API 设计是 Go 风格的。不是把 Python 的写法硬翻译成 Go,而是用 Go 的 interface、泛型、context 重新设计了一遍。
go
// Eino 的典型用法——创建一个 Chain
import "github.com/cloudwego/eino"
func main() {
// 1. 定义一个 ChatModel(对接大模型)
model := eino.NewChatModel(...)
// 2. 定义一个 Tool(Agent 能用的工具)
weatherTool := &WeatherTool{}
// 3. 用 Chain 串起来
chain := eino.NewChain().
AppendChatModel(model).
AppendTool(weatherTool)
// 4. 运行
ctx := context.Background()
result, err := chain.Invoke(ctx, "今天北京天气怎么样?")
}后面每一章用到 Eino 的哪个模块,我都会详细展开。这里只是让你先"看个脸熟"。
2.4.2 你会遇到的Eino核心模块
2.4.3 其他你会遇到的库
做 Go AI Agent 开发,除了 Eino,还有一些常用的库。不要求你现在记住,后面用到的时候我会讲:
| 库 | 用途 | 什么时候用到 |
|---|---|---|
net/http | 标准库HTTP客户端 | 调用LLM的REST API(Eino已经封装好了,一般不需要直接用) |
google.golang.org/grpc | gRPC通信 | 工具服务化、MCP协议实现(第13章) |
github.com/redis/go-redis | Redis客户端 | Agent记忆持久化(第7章) |
github.com/prometheus/client_golang | 指标采集 | Agent可观测性(第12章) |
encoding/json | JSON处理 | LLM的请求和响应都是JSON格式 |
和 Python 最大的不同:上面这些库,没有一个需要"系统依赖"。Go 的依赖是纯 Go 代码,go build 的时候自动下载编译。你不需要装 C 库、不需要配系统环境变量。
2.5 不想花钱先学?Mock模式了解一下
2.5.1 一个真实的痛点
学 AI 开发最大的门槛不是技术,是钱。
调用大模型的 API 要花钱。一次对话几分钱到几毛钱,听起来不多,但你学一个项目跑几十次、几百次——积少成多,一个月几百块就没了。更别提有些模型 API 还要折腾网络问题。
我当年学 AI Agent 的时候就被这个问题困扰了很久。 所以这本书做了一个"Mock 模式"。
2.5.2 Mock 模式是什么
简单说:假装调用 AI,用预设的模拟数据代替真实的 API 返回。
一个环境变量就能切换:
bash
# Mock模式——零成本,离线也能跑
export USE_MOCK=true
go run main.go
# 真实模式——连真实 AI
export USE_MOCK=false
export API_KEY=你的key
go run main.go2.5.3 Mock 模式不是"假的"
有人可能会觉得:"Mock 模式不是骗自己吗?返回的都是假的,学个啥?"
不对。Mock 模式让你学的是"整个系统的骨架和逻辑",而不是"某一次 API 的返回内容"。
举个具体的例子——你在做智能客服项目的时候:
- 逻辑部分:用户提问 → 意图识别 → 查知识库 → 调用工具 → 生成回答。这一整条链路,Mock 模式全都能跑。
- AI 部分:只是最后"生成回答"这步用了模拟数据。
你做的是学会怎么搭这套系统,而不是"看 AI 说了一句什么话"。那套业务逻辑,Mock 和真实模式跑出来的是一样的。
学习路径我建议这样:
- 先用 Mock 模式把整个项目跑通(理解骨架)
- 然后再接入真实 API(理解 AI 的"灵魂")
- 两个都理解之后,你自己就能设计 Agent 系统了
2.5.4 Go 的 Mock 模式实现
和 Python 不同,Go 的 Mock 实现更自然——因为 Go 有 interface。
go
// 定义一个 ChatModel 接口
type ChatModel interface {
Generate(ctx context.Context, prompt string) (string, error)
}
// 真实实现:调用 OpenAI API
type RealChatModel struct {
client *openai.Client
}
func (m *RealChatModel) Generate(ctx context.Context, prompt string) (string, error) {
return m.client.Chat(ctx, prompt)
}
// Mock 实现:返回预设数据
type MockChatModel struct{}
func (m *MockChatModel) Generate(ctx context.Context, prompt string) (string, error) {
return "你好!我是AI助手(模拟模式)", nil
}
// 在 main 里根据环境变量选择
var model ChatModel
if os.Getenv("USE_MOCK") == "true" {
model = &MockChatModel{}
} else {
model = &RealChatModel{client: openai.NewClient(apiKey)}
}Python 做 Mock 通常要靠猴子补丁(monkey patch)或者依赖注入框架。Go 的 interface 让 Mock 天然就是一等公民——编译期就确保 Mock 和真实实现有完全相同的接口。
2.5.5 什么情况下不需要 Mock 模式
如果你的 API 有免费额度(比如某些国产模型),或者公司报销 API 费用,那直接上真实模式也行。
但即使如此,Mock 模式还有一个好处——离线跑。 你在高铁上、飞机上、没网的时候,照样能写代码、跑逻辑。这对 Go 开发者来说尤其重要——Go 的编译速度极快,改一行 go run 秒出结果,不用等网络请求。
2.6 本章小结
这一章我们没写一行 Agent 代码,但把最重要的准备工作做了:
- Go 安装与 Go Modules:一个
go mod init搞定依赖管理,不需要 venv、不需要 freeze - go.sum 自动挡:和 Python 的依赖地狱说再见,MVS 算法自动处理冲突
- 开发工具:VSCode + Go 插件日常开发,GoLand 大型项目,Playground 快速试代码
- Eino 全家桶地图:ChatModel、Tool、Memory、Chain、Graph——先认识,后面会详讲
- Mock 模式:零成本学完所有项目,Go 的 interface 让 Mock 实现更自然
✅ 知识点检查
学完这一章,试试回答这几个问题:
- [ ] Go Modules 和 Python 的 venv + pip 有什么本质区别?
- [ ]
go.sum文件的作用是什么?为什么不需要手动维护? - [ ] Go 做 Mock 为什么比 Python 更自然?
- [ ] Eino 的核心模块有哪些?各自负责什么?
📚 延伸阅读
- Go 官方文档:https://go.dev/doc/
- Eino 官方文档:https://www.cloudwego.io/zh/docs/eino/
- Go Modules 详解:https://go.dev/blog/using-go-modules
- 本书配套源码:关注公众号「图解AI系列」免费领取
🎯 下一章预告
第 3 章,我们快速回顾 Go 核心语法——
"写 Agent 之前,这些 Go 够用了——goroutine、channel、interface、泛型、context,五件套搞定。"

