Skip to content

第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/arm64

macOS 用户

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 或 ~/.zshrc

Windows 用户:下载 .msi 安装包,一路下一步就行。

装完别忘了设置 GOPATH(Go 1.16 之后 go modules 模式已经不强制要求了,但有些工具还会用到):

bash
go env GOPATH
# /Users/你的用户名/go

2.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

这一行命令做了三件事:

  1. 创建 go.mod——记录你的项目名和 Go 版本
  2. 以后 go get 的依赖会自动写入 go.mod
  3. go.sum 会自动生成——锁定每个依赖的精确版本和哈希值

对比 Python 的依赖管理

PythonGo
初始化项目python -m venv + pip installgo mod init
添加依赖pip install langchain==0.3.30go get github.com/cloudwego/eino@v0.3.0
锁定版本requirements.txt(手动)go.sum(自动)
安装所有依赖pip install -r requirements.txtgo 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

有几个值得注意的点:

  1. .env 存敏感信息——API Key 放这里,代码里用 os.Getenv() 读,别硬编码
  2. go.modgo.sum 必须提交到 git——和 Python 不同,Go 的依赖文件是项目的一部分,别人 clone 下来 go build 就能跑
  3. 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.0

Go 的解决方式是完全自动的——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 buildgo 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)
LangChainEino(组装 Agent 的积木箱)
LangGraphEino 的 Graph 模块(分支、循环、状态管理)
ChromaDB / FAISSEino 的 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/grpcgRPC通信工具服务化、MCP协议实现(第13章)
github.com/redis/go-redisRedis客户端Agent记忆持久化(第7章)
github.com/prometheus/client_golang指标采集Agent可观测性(第12章)
encoding/jsonJSON处理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.go

2.5.3 Mock 模式不是"假的"

有人可能会觉得:"Mock 模式不是骗自己吗?返回的都是假的,学个啥?"

不对。Mock 模式让你学的是"整个系统的骨架和逻辑",而不是"某一次 API 的返回内容"。

举个具体的例子——你在做智能客服项目的时候:

  • 逻辑部分:用户提问 → 意图识别 → 查知识库 → 调用工具 → 生成回答。这一整条链路,Mock 模式全都能跑。
  • AI 部分:只是最后"生成回答"这步用了模拟数据。

你做的是学会怎么搭这套系统,而不是"看 AI 说了一句什么话"。那套业务逻辑,Mock 和真实模式跑出来的是一样的。

学习路径我建议这样

  1. 先用 Mock 模式把整个项目跑通(理解骨架)
  2. 然后再接入真实 API(理解 AI 的"灵魂")
  3. 两个都理解之后,你自己就能设计 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 代码,但把最重要的准备工作做了:

  1. Go 安装与 Go Modules:一个 go mod init 搞定依赖管理,不需要 venv、不需要 freeze
  2. go.sum 自动挡:和 Python 的依赖地狱说再见,MVS 算法自动处理冲突
  3. 开发工具:VSCode + Go 插件日常开发,GoLand 大型项目,Playground 快速试代码
  4. Eino 全家桶地图:ChatModel、Tool、Memory、Chain、Graph——先认识,后面会详讲
  5. Mock 模式:零成本学完所有项目,Go 的 interface 让 Mock 实现更自然

✅ 知识点检查

学完这一章,试试回答这几个问题:

  • [ ] Go Modules 和 Python 的 venv + pip 有什么本质区别?
  • [ ] go.sum 文件的作用是什么?为什么不需要手动维护?
  • [ ] Go 做 Mock 为什么比 Python 更自然?
  • [ ] Eino 的核心模块有哪些?各自负责什么?

📚 延伸阅读


🎯 下一章预告

第 3 章,我们快速回顾 Go 核心语法——

"写 Agent 之前,这些 Go 够用了——goroutine、channel、interface、泛型、context,五件套搞定。"