用 AI 学 Rust 的 100 天:记录每个阶段的有效方法和踩过的坑

📅 2026/7/25 7:19:11 👁️ 阅读次数 📝 编程学习
用 AI 学 Rust 的 100 天:记录每个阶段的有效方法和踩过的坑

用 AI 学 Rust 的 100 天:记录每个阶段的有效方法和踩过的坑

一、第 1~20 天:起步阶段 —— AI 给了我"假自信"

刚学 Rust 的时候我特别兴奋。不会写代码?直接问 AI:"用 Rust 写一个读取 CSV 的程序"。AI 几秒钟甩出一段代码,我复制粘贴跑起来,一行报错都没有。那种感觉就像自己突然变厉害了。

// ============================================================ // AI 帮我写的第一个 Rust 程序(第 3 天) // ============================================================ use std::fs::File; use std::io::{BufRead, BufReader}; /// 读取 CSV 文件并打印每一行 fn main() -> std::io::Result<()> { // 打开文件,? 操作符相当于"如果出错就直接返回错误" let file = File::open("data.csv")?; let reader = BufReader::new(file); // BufReader::lines() 返回一个迭代器,每次读取一行 for line in reader.lines() { let line = line?; // 如果读取出错,同样直接返回 println!("{}", line); } Ok(()) }

问题就出在这里——AI 帮我跳过了理解的步骤?操作符是什么意思?BufReaderFile有什么区别?我当时一概不知。代码能跑,但我不会改,也不会写新的。

到了第 15 天左右,我想做一个稍微复杂的功能——读取两个 CSV 文件做 join。AI 直接甩给了我一串.collect::<HashMap<_, _>>()iter().filter_map()的链式调用。这次我真的慌了,因为完全看不懂。

这个阶段的教训:AI 给的代码必须"消化"。我后来的做法是——每拿到一段 AI 代码,先不看它的实现,自己用注释逐行解释一遍。说不清楚的地方,就是知识盲区。

二、第 21~50 天:攻坚战 —— ownership 和 lifetime

ownership(所有权)和 lifetime(生命周期)是 Rust 最核心也最难的概念。这时候我发现了一个规律:AI 擅长解释"是什么",但不擅长帮你建立"感觉"

比如我问 "lifetime annotation 是什么意思?" AI 会给我一个很标准的回答:"生命周期标注告诉编译器引用之间的关系,确保引用始终有效。" 但这句话对于当时的我来说什么都没解决。

真正让我开窍的,是让 AI 用对比的方式解释。比如:

"请用对比的方式解释:在以下两个场景里,为什么第一个需要 lifetime annotation,第二个不需要?"

// ============================================================ // 场景 1:需要 lifetime annotation // 编译器不知道返回的引用来自 x 还是 y // ============================================================ fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } // ============================================================ // 场景 2:不需要 lifetime annotation // 编译器可以推断出返回值只依赖 self,不需要标注 // ============================================================ fn first_word(&self) -> &str { /* ... */ }

用对比方式让 AI 解释后,我给自己定了两个规则:

  1. 永远在代码里写场景对比。一个概念,至少需要两个不同场景的示例才能理解。
  2. AI 说完了,自己复述一遍。对着空白文件写一遍,不偷看 AI 的答案。

三、第 51~80 天:异步编程和 Tokio —— AI 最容易误导的阶段

异步编程是 AI 出错最多的领域。不是语法错误,而是设计层面的错误

有次我问 AI:"怎么在 async 函数里读一个大文件?" AI 给我写了:

// ============================================================ // AI 给的代码(有隐患!) // ============================================================ async fn read_large_file(path: &str) -> String { // 直接在 async context 里调同步 IO // 这会阻塞整个 worker 线程! std::fs::read_to_string(path).unwrap() }

这段代码能编译、能跑,但它在生产环境里会严重阻塞 Tokio 的 worker 线程。正确的做法是用tokio::fs

// ============================================================ // 正确版本:用 tokio::fs 做异步文件读取 // ============================================================ async fn read_large_file_correct(path: &str) -> String { // tokio::fs::read_to_string 不会阻塞 worker 线程 // 内部用 spawn_blocking 实现 tokio::fs::read_to_string(path).await.unwrap() }

这个阶段我学到的最重要的东西:AI 能帮你写代码,但不能帮你做架构决策。什么时候用tokio::fs还是std::fs,什么时候Arc还是直接传引用——这些问题 AI 的回答往往只是"能编译就行",而不是"这样做是对的"。

四、第 81~100 天:项目实战 —— AI 从"老师"变成"同事"

最后 20 天我做了一个完整的项目:一个基于 WebSocket 的实时日志查看器。这时候我对 AI 的使用方式彻底变了:

我不再让 AI"从头写",而是:

  1. 自己先画出模块图
  2. 自己写每个模块的代码
  3. 写完一个模块后,把代码贴给 AI:"请 review,指出可能的 bug 和性能问题"
  4. 根据 AI 的 review 做修改

这个模式下 AI 的价值反而更大了——它帮我发现了select!宏里的 task 泄露问题、StreamExt::buffer_unordered的使用时机问题。这些是我自己很难发现的。

五、总结

100 天用 AI 学 Rust,我最大的感受是:AI 是加速器,但不是替代品

四个阶段的 AI 使用方法总结:

  1. 起步期(1~20 天):AI 给代码,自己逐行解释,不懂去查官方文档。
  2. 攻坚期(21~50 天):让 AI 用对比方式解释概念,自己复述一遍再动手。
  3. 系统学习期(51~80 天):AI 写的是"能编译的代码",不是"正确的代码"。关键设计要自己判断。
  4. 项目实战期(81~100 天):让 AI 当 code reviewer,而不是代码生成器。自己先想、先写,再让 AI 挑毛病。

如果你也在用 AI 自学编程,我的建议很简单:永远不要复制粘贴你不理解的代码。哪怕只理解 80%,剩下的 20% 也要逼自己去查清楚。这 20% 的"不舒服感",才是真正学到东西的地方。