电影《克莱莉塔》剧情说明
2026-08-03 3438472
2026-08-03 0
AI 辅助编程的 7 个误区:把模型当高级搜索引擎是对它的最大浪费的重点在于把前置条件、操作顺序和容易误判的地方分清楚。
去年十二月,我在给 dayuan 做并发缓存层。ChatGPT 很自信地建议:"在 HashMap 外层包一个 Arc,多线程访问就安全了。"

我照做了。然后发现高并发场景下吞吐量从 5000 QPS 跌到了 300 QPS——因为所有读操作都在争同一个锁。最后我用 dashmap + 分片锁的方案才把性能拉回来。
这事让我明白一个道理:AI 给你的方案永远只是"能编译通过"的方案,不是"正确"的方案,更不是"好"的方案。
作为自学编程的人,我天然依赖 AI 来弥补知识短板。但一年多下来,我发现很多人在用 AI 编程时,陷入了 7 个典型的认知误区。
这是最常见的用法——也是最浪费的用法。
用户:tokio::spawn 怎么用?AI:这是文档……你在浪费模型的推理能力。你不是在用一个代码助手,你是在用一个美化版的 grep docs.rs。
正确的用法:
用户:我在写一个 WebSocket 服务,需要在 accept 新连接时同时维护一个全局的在线用户列表,支持广播。现在我用 Arc>> 存储在线用户 ID。每次广播都要遍历一遍,5000 并发时 Mutex 变成瓶颈了。不用给我写全代码,帮我分析三种可能的优化方向,以及每种在什么场景下适合。AI:好,我来分析:1. dashmap + 连接级别锁: 适用:读写比例均衡,需要强一致性 代价:内存占用比 Vec 高 30%2. 分片路由 + 无锁广播: 适用:写少读多(在线状态变更少,广播多) 代价:实现复杂度高,需要设计分片策略3. 事件总线 + 订阅模式: 适用:广播是主要操作,不需要存储状态快照 代价:需要引入消息中间件(如 tokio::broadcast) 看到了吗?你不是在问"怎么用",你是在把自己的设计困境描述给 AI,让它帮你做 trade-off 分析。
/// ❌ AI 写的代码,看起来没问题,直到你在生产环境看到 OOMasync fn process_all_users(user_ids: Vec) -> Vec {let mut tasks = Vec::new();for id in user_ids {// AI 不知道你的 user_ids 可能有 10 万个!tasks.push(tokio::spawn(async move {fetch_user_info(id).await}));}// 10 万个 task 同时运行 → 连接池耗尽 → OOMlet mut results = Vec::new();for task in tasks {results.push(task.await.unwrap());}results} 每次收到 AI 代码,带着这五个问题审一遍:
边界条件:如果输入为空会怎样?如果输入有 10 万条会怎样?错误处理:每个.await 点都可能出错,处理了吗?性能假设:这个操作是 O(1) 还是 O(n)?瓶颈在哪里?并发安全:多线程/多协程同时运行时,有数据竞争吗?资源泄露:文件句柄、网络连接、内存有没有正确释放?这是我刚开始用 ChatGPT 时最大的毛病。看到代码跑通了就以为学会了,一周后再遇到同样的问题——还是不会。
我的实践:AI 辅助学习的正确姿势
/// 场景:AI 生成了这段代码帮你解决问题/// 但你没有直接粘贴,而是逐行加注释来确保自己理解了use std::collections::HashMap;use std::sync::Arc;use tokio::sync::RwLock;/// 线程安全的缓存实现/// 追问 AI 的问题:/// Q: 为什么用 RwLock 而不是 Mutex?/// A: 因为缓存的读操作远多于写操作,RwLock 允许多个读并发/// Q: 为什么外面要包 Arc?/// A: 因为 RwLock 需要被多个 task 共享,Arc 提供多所有权pub struct Cache {inner: Arc>>,// ^^^ 多线程共享需要引用计数//^^^^^^ 读写锁:多个读者可以同时读,写者独占//^^^^^^^^^^^^^^^^^^^ 实际存储}impl Cache {pub fn new() -> Self {Self {inner: Arc::new(RwLock::new(HashMap::new())),}}/// 读取缓存(可以多个 task 同时读)pub async fn get(&self, key: &str) -> Option {let guard = self.inner.read().await;// ^^^^^^ 获取读锁,不阻塞其他读者guard.get(key).cloned()}// guard 在这里被 drop → 读锁释放/// 写入缓存(独占访问)pub async fn set(&self, key: String, value: String) {let mut guard = self.inner.write().await;// ^^^^^^^ 获取写锁,阻塞所有读者和写者guard.insert(key, value);}} 我的法则:AI 生成的代码,凡是不能逐行解释的,先弄懂再用。
AI 能告诉你"Tokio 的 runtime 有 block_in_place 这个函数"。但它不能告诉你什么时候不该用它。
/// ❌ AI 告诉你的:/// 在 async 函数里调用同步代码,用 block_in_place 就行async fn my_async_fn() {let result = tokio::task::block_in_place(|| {// 同步阻塞代码std::thread::sleep(Duration::from_secs(5));42});}/// 但 AI 不会告诉你的是:/// 1. block_in_place 会把当前 task 移出 worker 线程/// 2. 如果大量 task 都用 block_in_place,worker 线程池会"漏光"/// 3. block_in_place 只应在 CPU 密集计算中使用/// 4. 对于 IO 操作,应该用 spawn_blocking 或专门的异步 IO系统学习 > AI 问答。对于一个新概念,我的学习路径是:
读官方文档的 Overview(至少前 3 页)用 AI 回答"这个概念解决了什么问题"(不是"怎么用")写一个最小可运行的 demo故意写一个反例,看看会出什么问题最后才把 AI 生成的代码放进项目/// ❌ AI 写的用户认证代码 —— 永远不要这样用!#[derive(Deserialize)]pub struct LoginRequest {pub username: String,pub password: String,}async fn login_handler(req: LoginRequest) -> Result {// AI 的建议:直接拼 SQLlet query = format!("SELECT * FROM users WHERE username = '{}' AND password = '{}'",req.username, req.password// ← SQL 注入!);// 用 req.username = "admin' --" 就能绕过密码验证sqlx::query(&query).fetch_one(&pool).await?;Ok("登录成功")} 安全敏感的代码,永远不要让 AI 替你写。包括但不限于:
| 类别 | 为什么不能信 AI |
|---|---|
| SQL 查询拼接 | AI 不一定会用参数化查询 |
| 密码哈希 | AI 可能建议用 MD5/SHA1 |
| JWT 验证 | AI 可能跳过签名校验 |
| 权限检查 | AI 可能把授权逻辑写在客户端 |
| 加密实现 | 永远不要自己实现加密算法 |
// 你问 AI:// "这个函数有什么问题?帮我修复"pub async fn process_data(config: &Config, data: &Data) -> Result给 AI 提供上下文的最佳实践:
用户:我在维护一个多租户 SaaS 的数据处理管线。这个 process_data函数是管线的第二步,前一步是数据清洗,后一步是存储。当前的问题是:当租户数量从 10 增长到 1000 时,这个函数从 50ms 变成了 3s。[粘贴函数代码]我在怀疑 enrich 阶段的 HashMap 在租户维度做了 O(n²) 操作。帮我分析是否存在这个问题,以及如何修复。AI 不能替你选数据库,不能替你决定微服务拆分,不能替你评估技术债。因为架构决策的核心不是技术优劣,而是你今天有多大的团队、明天要支持多少用户、三个月后的需求是什么——而这些信息都不在模型的训练数据里。
具体来说:
需求阶段:把需求描述给 AI,让 AI 用三种不同方案各写 5 行伪代码。比较思路,不比较代码细节。设计阶段:自己画出数据流图或状态机图,让 AI 挑漏洞。实现阶段:自己写核心逻辑。AI 帮忙生成测试用例、文档注释、CLI 参数定义。审查阶段:把自己的代码给 AI,限定问题"这段代码有哪些我没考虑的边界情况?"重构阶段:功能验证通过后,让 AI 提出重构建议——这时候它已经有了完整上下文。AI 辅助编程一年多,我对 AI 的定位经历了三次迭代:
第一阶段:AI 是代码生成器——"帮我写一个……"第二阶段:AI 是结对编程伙伴——"这里有问题,帮我看看……"第三阶段(现在):AI 是思维延伸——"我在做 X,有三种方案,帮我分析每种在 Y 场景下的 trade-off……"关键转变是:从"让 AI 替我想"变成了"我思考,AI 检查"。的我之所以能靠自学转行,很大程度上受益于 AI。但我也看到太多人陷入"AI 写了代码 → 跑通了 → 以为自己学会了"的循环里。这不是在学习,这是在制造技术债——只不过债主是你未来的自己。
记住两件事:
AI 写代码只节省了你 20% 的时间,但如果你不理解它写的代码,未来修 bug 会多花 200% 的时间。好的开发者不是能快速写出代码的人,而是能判断"这段代码不该这么写"的人。AI 不能帮你做这个判断——只有你自己的理解能。