
你让 AI 解释了一遍 Go 的 Context 取消机制。
它给了你一段教科书般的回答:父 Context 调用 cancel() 时,通过关闭 Done() channel 向所有子 Context 广播取消信号。子 Context 在 select 中监听 ctx.Done(),收到信号后执行清理逻辑并退出。整个传播是树状的——每个 WithCancel/WithTimeout 创建的子节点都注册在父节点的 children map 里,父节点取消时遍历 children 逐个触发。
清晰。完整。层次分明。
你点点头。懂了。甚至还追问了一句"propagateCancel 的作用是什么",AI 回答得同样漂亮。你在心里给自己打了个勾:Context 取消机制——搞定。
第二天面试。
面试官是个写了五年 Go 的后端 Lead,语速不快,问题很直接:“Context 的取消信号是怎么向下传播的?能说说底层的机制吗?”
你张嘴——
空白。
不是完全空白。你记得"父取消子也取消"。你记得有个 Done() channel。但传播的具体路径?children 注册发生在什么时候?cancelCtx 和 timerCtx 的区别?propagateCancel 里那个 goroutine 是做什么的?
全是空白。
你开始试图组织语言。“就是…父 Context 会通过 channel…然后子 Context 就会…"——说了半天,说的是昨天 AI 回答的第一句话的残影。后面的全没了。
面试官礼貌地等了几秒,然后说:“没关系,我们换下一题。”
这不是健忘。你昨天明明"学过"这个知识。你甚至还觉得自己理解得挺深入的——毕竟你还追问了 propagateCancel。
这是一种更隐蔽的东西:你从来没有真正理解过。
AI 给你的是一个答案,不是一段记忆。你看到了一栋完整的房子,但你从没动手搬过一块砖。所以当你需要自己搭的时候——你连地基长什么样都不知道。
你拥有的是检索记录,不是知识。
这种感觉,如果你天天用 AI 学东西,你大概不陌生。
一、为什么 AI 特别容易让你"以为自己会了”
我们先给这个现象一个名字:知识幻觉——你以为自己掌握了某个知识,实际上只是知道怎么获取到它。
知识幻觉不是新概念。搜索引擎时代就有——你觉得自己"知道"很多东西,其实只是"知道去哪搜"。但 AI 把这个问题显著放大了。
为什么?因为传统搜索引擎给你的是"指向答案的链接"——你很清楚那是别人写的,你只是找到了它。但 AI 给你的是"直接的、对话式的、仿佛为你量身定制的解释"——你的大脑很难把它和"我自己想明白的"区分开来。
具体来说,AI 有三个特性叠加在一起,构成了一台完美的"能力幻觉制造机":
第一,AI 的回答太流畅了。
认知心理学里有个经典发现叫"流畅性错觉"(Fluency Illusion):当信息呈现方式越流畅、越有条理,你的大脑越容易把"这段话我读懂了"误判为"这个东西我理解了"。
你试过读一本排版精美、逻辑清晰的教科书,读完觉得"全懂了",合上书后什么都想不起来吗?
AI 的回答比任何教科书都流畅。它的格式工整、逻辑递进、措辞精确、还会根据你的问法调整解释深度。这种高度流畅的呈现方式,恰恰最大化了你的流畅性错觉。
你读完一段 AI 的解释,感觉通透清晰。但那份通透是 AI 的——它确实理解了。而你只是阅读了一份清晰的文本。理解和阅读理解之间,差着一整个"自己构建"的过程。
第二,获取答案的成本太低了。
学习中的困难不是 bug,是 feature。
你卡在一个概念上,Google 了半小时,看了三篇博文,最终在 Stack Overflow 的一个高赞回答里突然明白——“啊,原来如此!“那个顿悟时刻之所以让你记忆深刻,是因为你为它支付了认知代价。
认知科学管这叫**“生成效应”(Generation Effect)**:在学习阶段主动构建信息(哪怕构建得不完美)比被动接收相同信息的记忆留存率高得多。
AI 消除了几乎所有的认知代价。
你问一句话,2 秒得到完整答案。没有卡住。没有挣扎。没有那个"看了三篇博文突然贯通"的顿悟时刻。你的大脑没有为这段知识支付过任何代价。
你的大脑没有为这段知识支付过任何代价——所以它也不会为你保留它。
第三,AI 让你以为你没有在"外包思考”。
这是最微妙也最危险的一点。
我们来做一个对比:
计算器不让你以为自己会算数——你很清楚离了计算器,三位数乘法你做不了。你对计算器的依赖是显式的、你自知的。
GPS 不让你以为自己会认路——你知道没导航你找不到那家新开的餐厅。你不会因为用了三年 GPS 就觉得自己方向感变好了。
但 AI 让你以为自己会编程。
为什么?因为 AI 给你的不只是"一个答案”,而是"一段看起来像你自己思考后写出来的代码/解释"。它用第二人称跟你对话,它会说"你可以这样理解…",它模拟了一个导师一对一辅导你的场景。于是你的大脑不自觉地把这段对话体验标记为"我经过思考后得出了结论"——而不是"我从一个工具获取了信息"。
对计算器和 GPS,你知道自己在外包。对 AI,你甚至不觉得自己在外包。
你可能会说:被动学习本来就记不住啊。读文档读博客不也一样会忘?跟 AI 有什么特殊关系?
没错。被动学习的记忆弱点是普遍规律——这不是 AI 发明的问题。但 AI 特殊在两件事:第一,它系统性地把你推向最被动的学习模式。文档至少让你自己翻页、自己找信息、自己组织理解路径。AI 直接把组织好的答案端到你面前——你连"主动搜索"这个最低限度的认知参与都省了。第二,它让你对"自己正在被动学习"这件事毫无察觉。读文档时你知道自己在读别人写的东西。用 AI 时你觉得自己在"思考"和"对话"——但实际上你只是在接收。
AI 不是制造知识幻觉的唯一原因。但它是把"被动学习陷阱"最大化、最隐蔽化的工具。
这不只是我个人的体感。如果你在技术社区待过几年,你一定见过这个模式:有人能对着 AI 流畅地"学习"一整套新技术栈,但真到独立解决问题时——调试一个诡异的 bug、做一个没有现成方案的架构决策——他们卡住了。不是不知道方向,是"以为自己知道怎么做,实际动手时做不出来"。
知道和做到之间,隔着一整个"自己构建"的过程。AI 让你跳过了这个过程,但也让你以为你没跳过。

二、一把尺子:检索能力 vs 创造能力
“知识幻觉"听起来像个学术概念。但它有一个非常简单的判定方法——简单到你现在就可以做。
你对任何一个知识的掌握程度,可以用一把尺子来衡量:
关掉所有工具之后,你还能做到多少?
这把尺子把你的知识分成两种状态(这不是什么新概念——认知科学有大量类似的分层框架。但在 AI 学习的场景下,它需要一个可操作的判定方法):
检索能力——你知道这个东西存在,你知道去哪找到它,你在有工具辅助的时候能快速获取到正确答案。你拥有的是"通往知识的路径”,而不是知识本身。
创造能力——你理解底层逻辑,你内化了它的运作方式,你能在没有任何外部辅助的情况下,从空白开始重建它。知识在你的大脑里形成了可调用的心智模型。
听起来像废话?来看一个具体的例子。
你问 AI:“Go 里怎么用 sync.WaitGroup 等待一组 goroutine 完成?”
AI 给了你一段完美的示例代码:var wg sync.WaitGroup,wg.Add(n) 在外面调,每个 goroutine 里 defer wg.Done(),最后 wg.Wait() 阻塞等待。你复制到自己的项目里,编译通过,跑起来了。完美。
这个时刻——你"会用 WaitGroup"了吗?
如果"会用"的标准是"在有 AI 的情况下能正确使用"——是的,你会了。这是检索能力。你知道有 WaitGroup 这个东西,知道问 AI 就能拿到标准用法。
但如果有人让你在白板上从头写一个——不许查任何东西——你能回答这些问题吗?
- Add() 为什么必须在 goroutine 启动前调用?如果在 goroutine 内部调会怎样?
- Done() 如果多调了一次会发生什么?
- Wait() 在底层是怎么实现阻塞的?是 channel 还是信号量?
- 如果你需要等待的 goroutine 数量在运行时才知道,WaitGroup 还适用吗?
如果你能流畅地回答——这是创造能力。WaitGroup 的心智模型在你的大脑里形成了一个完整的、可推理的结构。
如果你开始卡顿、开始猜——那你之前只是在用 AI 检索。你拥有的是 AI 给你的那段代码,不是对 WaitGroup 的理解。
在这种学习模式下,你学到的东西很容易停留在"检索能力"的层面。 你知道了很多"答案",但不拥有产生这些答案的"能力"。
这不是 AI 的错。AI 就是一个极其高效的检索增强工具——这本来就是它的设计目的。问题不在于 AI 给了你答案,问题在于——你把"高效地获取答案"这件事,误以为是"深度地学会了"。

当然,这里必须承认一个边界:不是所有知识都需要"创造能力"级别的掌握。
你不需要记住 fmt.Sprintf 的所有格式化动词——这种事确实应该让 AI 帮你。你不需要背 HTTP 状态码表——查就行了。对于这类"参考性知识",检索能力完全够用。AI 在这些场景下是纯增益。
但有些东西不一样。
架构设计中的 trade-off 直觉——你为什么选微服务而不是单体?不是因为你读过一篇对比文章,而是因为你亲身经历过单体膨胀后的痛苦。这种直觉,不是检索得来的。
调试时的方向感——log 里出现了一个诡异的错误,你凭经验直觉"大概率是连接池耗尽"。这种直觉来自你无数次调试的累积编码,不是来自"问 AI 这个错误是什么意思"。
面对全新问题时的类比能力——你从没见过这个场景,但你能从以前解决过的问题里抽取模式来应对。这种迁移能力需要深层理解,不是表层记忆。
这些能力的共同点是:它们需要你真正理解了底层的"为什么",而不只是知道表层的"怎么做"。
那么问题来了:你怎么知道,你现在对某个知识的掌握,到底是停留在"检索"还是已经到了"创造"?
答案很残忍,但很简单。
三、我跑了个实验
我决定拿自己做一次测试。
不是设计一个复杂的实验——就是最朴素的方法:用 AI 学一个新东西,然后关掉 AI,看自己能独立做到多少。
实验对象:Go 的 bubbletea 库。这是 Charm 生态的一个终端 UI 框架(TUI),用来写命令行界面的交互式应用。我之前只知道这个库存在,没实际用过。选它是因为:有一定学习曲线,但 30 分钟能覆盖基本概念;它的 Model-Update-View 架构对 Go 开发者来说有一定新鲜度。
学习方式:打开 Claude,用最自然的方式学 30 分钟。
我做了以下事情:
- 问了 bubbletea 的核心架构(“它的编程模型是什么?")
- 请 AI 给我一个完整的示例(一个简单的计数器)
- 读了示例,觉得有几个不理解的概念,追问了 tea.Cmd、tea.Msg 的具体用法
- 让 AI 解释了键盘事件处理的模式
- 最后让 AI 帮我理了一下"如果我要写一个 TODO 列表 TUI,需要哪些部分”
这就是大部分人用 AI 学习的标准流程。问概念、看示例、追问细节、走一遍思路。
30 分钟后,我对自己做了一个自评。以下是我觉得自己"掌握了"的 7 个核心概念:
- tea.Model 接口的三个方法——Init()、Update()、View()
- tea.Cmd 的概念——异步操作的返回方式
- tea.Msg 自定义消息——怎么定义自己的事件类型
- 键盘事件处理——tea.KeyMsg 的模式匹配
- 列表渲染——循环遍历 items + 光标位置标记
- 状态切换——在 Update 函数中根据不同 Msg 改变 Model 状态
- tea.Program 的启动方式——tea.NewProgram(model).Run()
7 个概念,30 分钟。感觉效率很高。如果这是一次技术分享的准备,我会觉得自己"差不多掌握了 bubbletea 的基础"。
然后我关掉了 Claude。关掉了浏览器。关掉了所有 bubbletea 相关的文档标签页。
打开一个空白的 main.go 文件。
任务很简单:从零写一个能用的 TODO 列表 TUI。能添加条目、删除条目、上下移动光标。用 bubbletea 实现。
不许查任何东西。卡住就卡着。
结果如下:
| 概念 | 我以为"会了" | 关掉 AI 后实际情况 |
|---|---|---|
| Model 接口三方法 | ✅ | ✅ 顺利写出——记住了签名和各方法的职责 |
| tea.Cmd 返回方式 | ✅ | ❌ 知道有这东西,但返回值的类型和用法完全想不起来 |
| 自定义 Msg | ✅ | ❌ 不记得怎么定义一个 Msg 类型,也不记得怎么在 Update 里收它 |
| KeyMsg 处理 | ✅ | ✅ 顺利写出——键位判断的 switch 模式跟平时写 Go 一样熟悉 |
| 列表渲染 | ✅ | ⚠️ 循环遍历能写,但光标标记的具体实现卡住了(cursor == i 时加前缀这个模式不确定) |
| 状态切换 | ✅ | ❌ 知道是在 Update 里做,但具体的状态管理模式想不起来 |
| Program 启动 | ✅ | ✅ 一行代码——tea.NewProgram(model).Run()——这个太简单了 |
以为掌握 7 项。实际能独立使用:3 项(另有 1 项能做一半)。
超过一半的东西,关掉 AI 就做不了了。
这个数字让我停了几秒。
30 分钟的 AI 学习,感觉上效率极高——我"覆盖"了 7 个概念。但真实留存?不到一半。超过一半的"学习成果",在关掉 AI 的瞬间蒸发了。
更有意思的是规律。我去看了哪些留下了、哪些没留下,发现了一个非常清晰的模式:
留下的三个(Model 接口、KeyMsg、Program.Run)有一个共同点:它们要么跟我已有的知识结构强对齐——比如 Model 的三个方法对应 Go 的 interface 概念、KeyMsg 的匹配对应 switch-case——要么信息量极低(一行代码记住了)。
换句话说:我能理解"为什么是这样"的东西,留下了。 Model 接口为什么是这三个方法?因为 Elm Architecture 的 MVU 模式就是这么设计的,跟 React 的 state/render 类似——我有类比基础。
没留下的三个(Cmd、自定义 Msg、状态切换)也有一个共同点:我只是"看过 AI 给的示例,觉得合理、觉得能理解"——但从来没有自己"从空白构造过一次"。
AI 的示例太好了。它给的代码清晰完整,我读完觉得"嗯,合理"——然后就跳到了下一个问题。我跳过了那个最关键的步骤:自己从头尝试写一遍,哪怕写错。
“看懂别人写的"和"自己能写出来"之间,差着一整个认知鸿沟。AI 把前者变得极其容易——但这恰恰让你误以为你已经跨过了后者。
这就是检索和创造的分界线:你有没有从空白开始,自己构造过一次。

四、关掉 AI 写一遍——三步自测协议
基于这个实验的发现,我整理了一个简单的自测方法。本质上这就是 Active Recall——但针对 AI 学习场景做了两个调整:一个前置动作(在关掉 AI 之前先固定预期),和一个后置决策(区分哪些需要内化、哪些不需要)。
三步。不需要特别的工具。每次 5 分钟。你现在就可以用。
Step 1:学完后,花 2 分钟列出"我以为我会了什么”
用 AI 学完一个新东西之后,不要急着关掉对话窗口。在关掉之前,花 2 分钟做一件事:
在一张纸上(或一个空白文件里),快速列出你"以为自己现在掌握了"的 5-8 个要点。
不需要很精确。“我会用 Context 传取消信号了”、“我知道 WaitGroup 的三个方法了”——这种粒度就够。
这步的核心目的是固定一个锚点:你对自己的学习成果有什么预期。后面要用这个预期来和现实对比。
关键:必须在关掉 AI 之前写。不要关掉之后再回忆——那样你会无意中把"知道自己忘了什么"也当成"还记得什么",数据就不准了。
Step 2:关掉一切,从空白开始输出
关掉 AI。关掉浏览器里所有相关标签页。关掉笔记。
打开一个空白编辑器(如果是编程知识),或者拿出一张白纸(如果是概念/架构知识)。
从零开始。尝试独立输出你刚才学的东西。
如果是学了一个库的用法——尝试从空白 main.go 写一个简单的应用。 如果是学了一个架构概念——尝试从空白画出它的核心组件和交互流程。 如果是学了一个算法——尝试从空白写出伪代码。
**不需要完美。**你的目标不是"写出一个能编译通过的完整程序"。你的目标只是看看自己"能走多远"——能独立写出哪些部分,在哪里卡住。
能写出来的部分——恭喜,那是你的了。它已经从"检索记录"变成了"大脑里的知识"。
卡住的地方——标记它。不要打开 AI 去补。就让它卡着。那个"卡住"的感觉本身就是信息:它告诉你,这个知识点你只是"看过",还没有"内化"。
Step 3:对比落差,标记你的真实掌握地图
回过头,把 Step 1 的预期清单和 Step 2 的实际产出做一个简单对比:
创造级掌握(关掉 AI 也能做到的):
- 这部分是真正属于你的。不需要额外刻意练习。
- 对应的知识你可以放心依赖——面试、工作中、断网时,它都在。
检索级掌握(关掉 AI 就卡住的):
- 这部分你只是知道"存在这个东西"和"大概在哪能找到"。
- 你现在需要做一个判断——
对"检索级"的每个知识点,问自己一个问题:这个东西,我需要把它升级到"创造级"吗?
如果不需要(多数情况下):完全没问题。接受它是"检索级"就好。API 的参数顺序、配置文件的格式、某个工具的 CLI 用法——这些东西让 AI 帮你记就行,不值得你花脑容量去内化。AI 在这些场景下是纯增益工具。
如果需要(少数关键知识):比如面试要用、工作天天用、或者它是更大知识体系的地基——那你需要做一件事:
关掉 AI,自己从头写一遍。
不看任何参考。挣扎着写。卡住就卡住。
那个"卡住→挣扎→想通"的过程,恰恰是深度编码发生的时刻。你在 Step 2 中体验到的那种卡顿感——那不是失败,那是学习真正开始的地方。
这个自测不需要每天做。也不需要对所有学过的东西做。只需要在以下时刻用一次:
- 你用 AI 学了一个你觉得"挺重要"的新东西
- 你准备把某个知识用在面试/工作/分享中
- 你已经连续三天用 AI 查同一个东西了(这是一个信号——如果你需要反复检索,说明你还没真正掌握)
每次 5 分钟。不多。

收束
回到开头那个场景。
面试官问你 Context 的取消传播机制。你张嘴——空白。
现在你知道为什么了。
现在你知道为什么了。你让 AI 解释完之后,点了点头,就跳到了下一个问题。你跳过了那个"自己从头梳理一遍"的过程。
AI 的回答太清晰了。清晰到你的大脑把"读懂了这段清晰的文字"误判为"我自己理解了这个机制"。
这不是 AI 的错。它做了它该做的事——高效地给你答案。但你需要知道的是:获取答案 ≠ 获得知识。看懂回答 ≠ 真的理解。
下次你让 AI 解释完一个你觉得重要的概念,觉得"我懂了"的时候。
试一件事。
关掉 AI。打开一个空白页。从头写一遍。
如果你能写出来——它是你的。
如果不能——你只是问到了一个答案。
而好消息是:从"问到了答案"到"真正学会",中间隔着一道门——那个你跳过的、卡住的、挣扎的过程。走进去之后还有路要走,但你起码知道门在哪了。
原文发布于 止语Lab