生锈的知识,还能不能重新上场?

Posted on 二 30 6月 2026 in Tech

Abstract 生锈的知识,还能不能重新上场?
Authors Walter Fan
Category Tech
Status v0.4
Updated 2026-06-30
License CC-BY-NC-ND 4.0

一个老程序员的扎心时刻

有些知识,年轻时像随身带着的瑞士军刀,掏出来就能用。过了几年再摸,刀还在,手感没了。

比如大型 C++ 和 Audio/Video 项目。以前看到音视频问题,脑子里会自然浮出采集、编码、RTP、抖动缓冲、解码、渲染那条链;看到 C++ 崩溃,也会下意识去想对象生命周期、线程同步、内存所有权、ABI、编译选项。可如果很久没碰,概念还认识,下手却会慢半拍。像多年没开的老车,钥匙插进去以后先咳嗽一下。

AI 出来以后,这种感觉更微妙。

一方面,它让你随时可以查:std::unique_ptr 怎么用、Opus packet loss concealment 是什么、WebRTC stats 里 jitter 怎么看,问一下就有答案。另一方面,它也容易让人产生错觉:既然 AI 都能讲,我是不是也还会?

我越来越觉得,AI 时代真正危险的不是知识生锈,而是你不知道它已经生锈了

这就像《方世玉续集》里元奎饰演的李国邦。公开资料里能查到,这个角色是苗翠花的师兄、方世玉的师叔,为人胆小,口头禅是“安全第一”。影迷更津津乐道的,是他那种带着冷幽默的江湖自信:

“别以为我退隐江湖了,告诉你,我的功夫是没生锈的。”

结果呢?真到了要拼命的时候,“安全第一”没能挡住于镇海,“功夫没生锈”也救不了一个判断已经生锈的人。

程序员也一样。最怕不是不会,而是半会不会;不是忘了,而是记得一个过期版本;不是手生,而是手生还硬装手熟。

所以问题不是:长久不用的知识还能不能捡起来?

我的答案是:能。但不能靠情怀,也不能靠临时抱佛脚。要靠一套能让知识恢复战斗力的方法。


先承认一件事:知识一定会生锈

程序员最容易高估自己的“曾经会过”。

曾经写过 C++,不等于今天还能稳稳写出异常安全、生命周期清楚、并发不乱的 C++。曾经做过音视频,不等于今天还能快速判断一个卡顿问题到底是网络、编码器、jitter buffer、设备路由,还是线程调度。曾经读过一堆 RFC,也不等于今天还能在凌晨两点的线上事故里把关键字段想起来。

知识不用,会发生三种退化。

第一种是细节退化。API 名字、参数顺序、编译选项、工具命令会忘。这个问题最轻,AI 和文档都能补。

第二种是手感退化。你知道大概方向,但下手慢,调试慢,看到错误信息反应慢。像很久没打篮球,投篮姿势还在,球就是短半截。

第三种最危险,是判断退化。你以为自己知道,其实场景变了、工具变了、默认值变了、最佳实践也变了。旧经验在新环境里不是资产,可能变成负债。

比如 C++。你记得“手动管理内存很危险”,但如果只停在这句口号上,今天面对 std::shared_ptr 循环引用、lambda 捕获悬空引用、协程生命周期、跨线程回调,照样会摔跤。

再比如 Audio/Video。你记得“丢包会卡”,但现在的问题可能不是简单丢包,而是关键帧没及时到、参考帧被污染、硬件解码器输出格式变了,或者 AI 降噪把人声边缘吃掉了。旧地图有用,但不能当 GPS。

承认生锈,不丢人。假装没锈,才危险。

先放一张“锈斑检查表”。看完这张表,你大概就知道自己到底是忘了几个 API,还是判断链路已经不太稳了。

退化类型 表面现象 C++ 里的典型表现 Audio/Video 里的典型表现 AI 能补什么 人必须练什么
细节退化 名字想不起来 忘了 std::move 触发条件、CMake target 写法 忘了 stats 字段名、RTCP feedback 类型 查文档、列清单、解释概念 快速查证和最小复现
手感退化 知道方向但下手慢 编译错误看半天,sanitizer 报告读得慢 pcap、stats、日志串不起来 生成示例、辅助解读日志 亲手 debug、亲手跑实验
判断退化 旧经验误导新场景 shared pointer 滥用、异步回调生命周期误判 把所有卡顿都归因于“网络不好” 提供候选假设和检查项 排优先级、找证据、做取舍

AI 的作用:不是替你练功,而是帮你搭靶场

很多人用 AI 复习旧知识,姿势是这样的:

请给我讲讲现代 C++。
请总结一下 WebRTC 音视频技术。
请列出音视频开发面试题。

这当然有用,但只是热身。它让你觉得“我又懂了”,却未必让你真的能干活。

AI 更好的用法,不是当老师单向讲课,而是当陪练、助教、出题人、记录员。你要让它帮你搭靶场,而不是替你打靶。

我比较推荐这类问法:

我很久没写大型 C++ 项目了,想在两周内恢复到能参与代码评审和小型模块开发的状态。
请帮我设计一个训练计划:

1. 先测我哪些知识已经生锈
2. 每天安排一个 60 分钟练习
3. 每个练习必须有可运行代码或可验证输出
4. 重点覆盖所有权、并发、构建、调试和性能
5. 最后给一个小项目作为验收

再比如 Audio/Video:

我想重新熟悉实时音视频排障。
请生成 10 个故障场景,每个场景包含:

1. 用户现象
2. 可能的故障域
3. 需要采集的 stats 和日志
4. 最小复现实验
5. 不要直接给结论,先让我判断

注意这里的关键:让 AI 出题,但人必须作答;让 AI 整理,但人必须验证;让 AI 提醒,但人必须动手。

知识恢复不是看懂答案,而是重新建立“从现象到判断再到行动”的回路。


一套让知识重新可战的四层方法

我现在更愿意把知识恢复分成四层:地图、索引、演练、验收。

这四层不是线性读书流程,更像一个闭环:

          +----------------------+
          |                      v
地图 -> 索引 -> 演练 -> 验收 -> 复盘 / Runbook
 ^                                |
 |                                |
 +---------- 新问题 / 新事故 ------+

地图让你知道自己在哪,索引让你快速找到工具,演练让知识回到手上,验收防止“我看懂了”的幻觉。最后的复盘和 Runbook,则是为了下一次别从零开始。

@startuml
skinparam backgroundColor white
skinparam shadowing false
skinparam defaultFontName "Arial"
skinparam roundcorner 12
skinparam activity {
  BackgroundColor #F8FAFC
  BorderColor #334155
  FontColor #0F172A
  DiamondBackgroundColor #E0F2FE
  DiamondBorderColor #0284C7
}

title 生锈知识恢复闭环

start
:地图\n画出知识骨架;
:索引\n接到真实材料;
:演练\n用小场景恢复手感;
if (验收通过?) then (是)
  :复盘 / Runbook\n沉淀可复用经验;
else (否)
  :标记锈斑\n补证据和实验;
endif
:进入下一次真实问题;
repeat
  :更新地图和索引;
  :继续演练;
repeat while (仍有高风险锈斑?) is (是)
->否;
stop
@enduml

生锈知识恢复闭环

1. 地图:先画出知识骨架

长久不用的领域,别一上来就钻细节。先画地图。

以 C++ 为例,我会先画这几块:

  • 语言核心:对象模型、值语义、引用、移动语义、模板、异常
  • 资源管理:RAII、智能指针、文件句柄、锁、线程生命周期
  • 并发:std::thread、mutex、condition variable、atomic、future、协程
  • 工程化:CMake、编译链接、sanitizer、单元测试、性能分析
  • 代码质量:异常安全、接口边界、依赖管理、可测试性

以 Audio/Video 为例,则可以先画这条链:

采集 -> 预处理 -> 编码 -> 打包 -> 传输 -> 抖动缓冲 -> 解码 -> 渲染

每一段下面再放关键问题:

  • 采集:设备枚举、采样率、声道、权限、路由切换
  • 预处理:AEC、AGC、NS、VAD、音量检测
  • 编码:Opus、H.264、VP8/VP9/AV1、码率、帧率、关键帧
  • 传输:RTP、RTCP、NACK、FEC、RTX、TWCC、拥塞控制
  • 播放:jitter buffer、同步、渲染队列、延迟、卡顿

地图的目的不是显摆“我知道很多名词”,而是防止自己迷路。你至少要知道:我现在忘的是哪一块,不能把一个角落的熟悉,误认为整片大陆都还在掌控中。

2. 索引:把知识接到真实材料上

有地图还不够,还要有索引。

索引不是收藏夹。收藏夹最容易变成数字坟场,看着满满当当,实际没人扫墓。真正有用的索引,要能指向“我需要时立刻能用”的材料。

我会给每个领域留几类入口:

  • 官方文档:标准、API reference、项目 wiki
  • 经典文章:自己确认过、确实讲清楚的材料
  • 代码样例:能编译、能运行、能改的最小例子
  • 排障手册:常见症状、日志字段、检查顺序
  • 个人笔记:踩过的坑、修过的 bug、当时的判断过程

比如 C++,你可以保留一个 cpp-lab 仓库,里面不是大而全教程,而是小而硬的练习:

cpp-lab/
  ownership/
  move-semantics/
  concurrency/
  cmake/
  sanitizers/
  perf/

比如音视频,你可以保留一个 av-lab

av-lab/
  opus-playground/
  rtp-packet-dump/
  jitter-buffer-sim/
  webrtc-stats-parser/
  weak-network-cases/

索引的价值在于:当你三个月、半年、一年后回来,不用从互联网的汪洋大海里重新捞针。你打开自己的 lab,就知道从哪里热身。

3. 演练:用小场景恢复手感

知识恢复最忌讳“只看不练”。

看文章会产生一种温柔的错觉:这我懂。真正一写代码,编译器立刻帮你恢复谦逊。

我会把演练分成三种。

第一种是Kata,也就是小型招式练习。比如:

  • 用 RAII 封装一个文件句柄,要求异常安全
  • 写一个 thread-safe queue,用 condition variable 做阻塞等待
  • 用 AddressSanitizer 找出一个 use-after-free
  • 写一个简单 RTP header parser
  • 模拟 jitter buffer 在不同丢包率下的行为

第二种是病例复盘。找一个真实或半真实的问题,不急着看答案,先自己判断:

现象:用户说声音偶尔变成机器人音。
约束:网络 RTT 不高,但 jitter 有尖峰。
数据:audio concealment events 增加,CPU 偶尔飙高。
请判断前三个可能原因,并设计验证步骤。

第三种是小项目验收。不要大,一周能完成最好。比如:

  • 写一个命令行工具,读取 pcap 或日志,统计 RTP sequence gap
  • 写一个 WebRTC stats analyzer,把 jitter、RTT、packet loss 画成时间线
  • 写一个 C++ 小服务,包含配置、日志、测试、CI 和性能基准
  • 写一个音频小工具,读取 WAV,做音量归一化或简单频谱分析

小项目的作用不是产出伟大作品,而是逼你把散点知识重新接上线。能跑起来,能测,能解释,手感就回来了。

4. 验收:别用“我看懂了”骗自己

重新捡知识,必须有验收标准。否则很容易复习了三天,最后只获得一种“我好像又行了”的幻觉。

我给自己设的验收通常有四条。

第一,能复述模型。不用看资料,能把核心链路讲给一个聪明但不熟悉的人听。

第二,能写最小代码。不是复制,不是让 AI 一把梭,而是自己能写出核心骨架。

第三,能定位问题。给你一个症状和一组不完整日志,你能列出假设、证据、下一步实验。

第四,能审 AI 的答案。AI 给你一段 C++ 或一份音视频排障建议,你能看出哪里靠谱,哪里有风险,哪里缺证据。

最后一条尤其重要。AI 时代,很多人不需要从零写,但必须能审。审不出来,就会被漂亮答案带沟里。


两个真实感更强的工程例子

方法论说多了容易发飘,下面放两个工程里很常见、也很容易把人摔醒的例子。它们的价值不在“故事多精彩”,而在于能看出知识生锈以后,问题会怎样绕过你的自信。

例子一:C++ 异步回调里的悬空对象

很多 C++ 项目里都有这种代码味道:

class Session {
public:
    void start() {
        timer_.async_wait([this](const Error& err) {
            if (!err) {
                sendHeartbeat();
            }
        });
    }

private:
    Timer timer_;
};

这段代码第一眼看不吓人,甚至很“正常”。问题在于:回调执行时,Session 对象还活着吗?

如果对象已经被销毁,lambda 里捕获的 this 就变成了悬空指针。运气好,测试环境直接 crash;运气不好,线上偶发,堆栈还不稳定。你看日志像看悬疑小说,每个嫌疑人都有作案时间。

这种 bug 特别适合检验 C++ 手感是否生锈。

如果只是细节生锈,你会去查 lambda 捕获规则、智能指针用法,这还好补。如果是判断生锈,你可能会说“这里一直这么写,应该没事”,然后把一个生命周期问题当成偶发网络错误或线程调度问题。

比较稳的处理方式通常有几类:

  • 明确取消回调:析构或 stop 阶段取消 timer,保证回调不再触达对象;
  • 改用 weak_ptr:回调里先 lock(),对象不在就直接返回;
  • 拆清所有权:让异步任务拥有必要状态,而不是偷偷依赖外部对象还活着;
  • 用 sanitizer 验证:AddressSanitizer / ThreadSanitizer 比“我觉得没问题”靠谱得多。

这就是为什么我前面说,知识恢复不能只靠读。生命周期问题必须写、跑、崩、修,手才会重新记住那种边界感。

例子二:绿屏和马赛克,不一定只是“网络不好”

视频问题里,最容易误判的一句话也是:“网络不好。”

这句话不能说错,但太粗。像医生只说“你身体不舒服”,病人听了只想翻白眼。

视频绿屏和马赛克,是音视频工程里非常有画面感的事故。用户不需要懂 H.264、VP8、YUV,也不需要看 stats。他只要截一张图发过来,整个群都会安静两秒:远端人脸变成一片绿色,或者画面碎成马赛克,像压缩算法喝多了。

这类问题常见于几个场景:

  • 弱网恢复后,画面没有立刻恢复正常,而是持续马赛克;
  • 切换摄像头、切换分辨率、切换 simulcast 层以后,部分客户端绿屏;
  • 某些 Android 机型或某些显卡上容易出现,换软解后消失;
  • 共享屏幕还好,摄像头视频更容易花;
  • 声音正常,视频单独坏,看起来不像整条连接断了。

第一反应当然会怀疑网络:是不是丢包太高?是不是码率估计太激进?是不是 NACK/RTX 没救回来?这些都该查,但不能只查这些。

马赛克通常和参考帧被破坏有关。视频编码不是每一帧都完整保存,大量 P/B 帧都依赖前面的参考帧。如果关键的参考帧丢了、错了,后面的帧就会“认真地错下去”。这时候 decoder 不是完全不能解,而是带着错误参考继续解,用户看到的就是一片一片的花屏。解决思路通常不是盲目加码率,而是要看:

  • 丢包后有没有及时发 PLI/FIR 请求关键帧;
  • 关键帧是否真的到达,还是被网络继续丢掉;
  • NACK/RTX 回来的包是否已经错过播放窗口;
  • 切换分辨率或 simulcast 层时,是否等到了新层的 keyframe;
  • stats 里的 keyFramesDecodedframesDroppedfreezeCount 有没有异常。

绿屏则常常是另一类味道:像素格式、stride、crop 或硬件解码器状态出了问题

比如解码器输出的是 NV12,渲染侧却按 I420 去解释;或者分辨率变了,Y plane、UV plane 的 stride 没更新;或者硬解在 resolution change 之后没有正确 flush/reconfigure,上一帧的纹理状态被继续拿来画。结果就是用户看到一整块绿色、紫色,或者半边正常半边异常。

这种时候,最小验证实验很重要:

  • 同一条视频流,软解是否正常、硬解是否异常;
  • 同一设备上,H.264 和 VP8/VP9 表现是否不同;
  • 关闭 simulcast 或固定分辨率后,问题是否消失;
  • 强制请求 keyframe 后,马赛克是否恢复;
  • 打印 decoded frame 的 width、height、stride、crop、format,是否和渲染侧一致。

这个例子的教训很朴素:

看到的现象 容易误判 真正要查的证据
弱网后持续马赛克 单纯网络差 PLI/FIR、keyframe 到达时间、参考帧是否恢复
切换分辨率后绿屏 编码器坏了 decoder reconfigure、SPS/PPS、frame width/height/stride/crop
只在部分设备出现 用户设备太差 硬解/软解对比、像素格式、GPU texture 更新
声音正常但视频坏 整条连接异常 audio/video stats 分开看,定位到视频解码或渲染链路

如果音视频知识生锈,很容易停在“网络不好”或“解码器有 bug”。这两句话也许都对,但都不够。工程上真正有价值的是继续往下问:是关键帧没来,还是参考帧坏了?是 codec 参数变化没处理,还是 YUV buffer 被错误解释?是媒体包问题,还是渲染层拿错了 stride?

这才是来之能战的知识。


一个两周恢复计划:以 C++ 和 Audio/Video 为例

如果要把 C++ 和 Audio/Video 重新捡起来,不追求“重回巅峰”,只追求“来之能战”,我会按两周安排。

先用一张表看全局:

阶段 时间 目标 产出物 验收标准
摸底 第 1-2 天 找出锈斑 诊断题、错题清单 能说清楚最弱的 3 个点
小练习 第 3-6 天 恢复手感 RAII、queue、RTP parser、jitter 模拟 每个练习能运行、能解释
小项目 第 7-10 天 串起链路 webrtc-stats-lite 或类似工具 有输入、输出、异常处理
病例复盘 第 11-14 天 训练判断 3-5 个故障病例分析 能列假设、证据和下一步实验

第 1-2 天:摸底,不急着补课

先让 AI 出一份诊断题,但自己答。

C++ 方向可以测:

  • unique_ptrshared_ptrweak_ptr 的适用边界
  • 移动构造和拷贝构造的触发场景
  • lambda 捕获引用的生命周期风险
  • std::atomic 和 mutex 的取舍
  • CMake target、include path、link library 的基本组织

Audio/Video 方向可以测:

  • RTP timestamp 和 sequence number 的作用
  • jitter、RTT、packet loss 的区别
  • NACK、FEC、RTX 的代价
  • AEC、AGC、NS 的常见副作用
  • 音画不同步可能从哪些层产生

摸底的目的不是考试,而是找到锈斑。

第 3-6 天:每天一个小练习

不要贪多。每天一个 60 到 90 分钟的小练习,做完要能运行。

比如:

  • Day 3:写 RAII wrapper,加单元测试
  • Day 4:写 thread-safe queue,用 sanitizer 跑一遍
  • Day 5:解析 RTP header,输出 sequence、timestamp、payload type
  • Day 6:写一个 jitter buffer 的简化模拟,观察乱序和丢包

这几天重点不是学新东西,而是让手重新相信脑子。

第 7-10 天:做一个小项目

选一个真实有用的小项目,比如 webrtc-stats-lite

输入:浏览器导出的 WebRTC stats JSON
输出:
1. RTT / jitter / packet loss 时间线
2. 码率变化
3. 音频 concealment 指标
4. 可疑时间段标记

实现可以让 AI 辅助,但关键设计自己定:

  • 数据结构怎么表示
  • 指标之间怎么关联
  • 哪些异常只提示,不下结论
  • 输出格式如何方便人读

做完以后,你对音视频链路和工程手感都会恢复一截。

第 11-14 天:做病例分析和代码审查

最后几天别再堆知识点,改做判断训练。

让 AI 生成几个故障病例,或者拿以前的线上问题复盘。每个病例按这个模板写:

现象:
初步假设:
需要的数据:
最小实验:
可能修复:
上线风险:
回滚方案:

同时找几段 AI 写的 C++ 或音视频代码做 review,重点看:

  • 生命周期有没有悬空
  • 错误处理是不是只写了 happy path
  • 并发有没有数据竞争
  • 日志有没有泄露隐私或打爆性能
  • 音视频判断有没有缺证据就下结论

到这一步,如果你能指出 AI 答案的漏洞,说明知识不只是热了,还开始恢复战斗力了。


防止再次生锈:要靠维护节奏,不靠热血

知识恢复一次不难,难的是别每次都从废墟里重建。

我现在比较相信一个很朴素的节奏。

每周:保留一块手感自留地

每周至少留一小段时间,关掉 AI 或限制 AI,只做一个很小的动手练习。

比如手写一个 parser,手调一个 sanitizer 报错,手读一段编解码代码。不是为了效率,而是为了保住那种“看到问题能下手”的肌肉记忆。

AI 可以提高产能,但不能替你保持手感。刀可以让别人磨,手不能让别人长。

每月:做一次知识巡检

每个月挑一个领域问自己三件事:

  • 这个领域最近有没有重要变化?
  • 我上次真正动手是什么时候?
  • 如果明天有人问我一个生产问题,我能不能提出验证路径?

答不上来,就安排一次小演练。

每季度:更新一次个人 Runbook

把你踩过的坑、查过的问题、验证过的结论写进自己的 runbook。

不要写成漂亮论文,就写成能救命的格式:

症状:
优先检查:
关键指标:
常见误判:
验证命令:
修复注意:

真正有价值的知识库,不是“我收藏了什么”,而是“下次出事时我少绕多少弯路”。

每半年:做一次小型回炉

半年不用的硬技能,默认手感下降。别争,争不过人性。

给自己安排一个周末或两三个晚上,做一次小项目回炉。不要等到面试、换岗、项目救火时才想起来。那时候再练,就像比赛前夜才找球鞋,多少有点狼狈。


几个常见坑:生锈不可怕,乱磨才可怕

第一,别用“看视频”代替练习。

视频看起来很顺,因为坑都被讲课的人替你踩平了。真正恢复能力,一定要自己遇到编译错误、数据不对、图画不出来、日志看不懂。痛感是学习的一部分。

第二,别让 AI 直接给最终答案。

你可以让 AI 提示、追问、出测试、生成对比表,但不要一上来就让它总结最佳实践。最佳实践如果没有经过你的场景过滤,就只是互联网平均值。

第三,别只补新知识,不修旧误解。

很多生锈的知识不是空了,而是旧了。旧经验最麻烦,因为它有熟悉感。你要专门问:我过去的做法今天还成立吗?有什么默认条件已经变了?

第四,别一恢复就接高风险任务。

刚回炉时,适合做工具、测试、review、低风险模块;不适合直接接核心链路大改。拳头刚热,别立刻去打擂台。先打沙袋,再上实战。


总结:AI 让知识更容易捡起,也让错觉更危险

长久不用的知识,当然能重新捡起来。

但捡起来不是把概念再读一遍,也不是让 AI 给你生成一份“从入门到精通”。真正有用的方法,是把知识重新接回四个东西:地图、索引、演练、验收。

一句话:

生锈的知识不可怕,可怕的是没有打磨就上战场;AI 不会替你长功夫,但可以帮你搭一个更好的练功房。

最后给自己,也给同样有点手生的老程序员一张清单。

行动清单

  • [ ] 给一个久不用但重要的领域画一张知识地图,标出最生锈的三块。
  • [ ] 建一个小型 lab 仓库,只放能运行、能验证、能复用的练习。
  • [ ] 让 AI 出题,不让 AI 直接给结论;先自己判断,再对答案。
  • [ ] 每周保留一次不用 AI 或少用 AI 的手感练习。
  • [ ] 每月更新一个 runbook 条目,记录真实坑、关键指标和验证路径。
  • [ ] 接高风险任务前,先用小项目或病例分析完成一次验收。

别做李国邦式的“安全第一”:嘴上说功夫没生锈,心里其实没做过验收。安全当然要第一,可前提是你真知道自己的功夫现在还剩几成。

功夫会生锈,没关系。定期擦,定期练,关键时刻还能拔得出来。


本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。