用AI写代码踩过的坑,我全替你记下来了

威武山峰
2026-07-12 09:55
阅读 641

作者按:带了五年应届生培训,我发现一个规律——现在的新人学技术,最大的障碍已经不是"看不懂语法",而是"不知道怎么用工具"。这篇文章,我把这几年带团队做技术探索时踩过的坑,尤其是围绕 GitHub Copilot 和 AI搜索 这两把"新武器"的使用心得,全写下来了。希望能帮你少走弯路。


一、先聊聊:为什么你需要关心 AI 辅助编程

我当初学编程的时候,遇到问题的第一反应是打开搜索引擎,敲一行关键词,然后在 Stack Overflow 的几十个回答里翻来翻去。那时候我们管这叫"面向搜索编程"。

但现在时代变了。

2023 年之后,我们团队开始系统性地引入 GitHub Copilot 作为日常开发工具,同时把 AI搜索(比如 Perplexity、Bing Chat、Google AI Overview 等)作为技术调研的辅助手段。一年下来,我观察到几个明显的变化:

  • 新人上手速度提升了大约 40%
  • 代码 review 时的低级错误减少了
  • 但同时也出现了一些新的问题——比如过度依赖 AI 生成代码、不理解生成逻辑、盲目信任 AI 输出等

所以这篇文章,我不会教你"怎么让 Copilot 帮你写代码"——这个太简单了。我要讲的是:在真实项目中,怎么把 AI 工具用好,以及我们踩过哪些坑。


二、环境准备:把工具链搭起来

在开始之前,你需要准备好以下环境。我列一个表,你照着来就行:

工具 用途 获取方式 备注
VS Code 代码编辑器 https://code.visualstudio.com 免费
GitHub Copilot 插件 AI 代码补全 VS Code 插件市场搜索安装 需要订阅,学生可免费申请
GitHub 账号 使用 Copilot 的前提 https://github.com 学生认证后可免费用
Node.js (LTS) 运行 JavaScript 项目 https://nodejs.org 建议装 18.x 或 20.x
AI搜索工具 技术调研辅助 Perplexity / Bing Chat 等 选一个你顺手的

2.1 安装 GitHub Copilot 的步骤

我当初第一次装 Copilot 的时候,折腾了快半小时,因为没搞清订阅和插件的关系。这里帮你理清:

第一步:确认你有 GitHub Copilot 订阅

1. 登录 https://github.com
2. 点击右上角头像 -> Settings
3. 左侧菜单找到 "Copilot"
4. 如果显示 "You have access to GitHub Copilot",说明OK
5. 如果没有,点击 "Enable GitHub Copilot" 并按提示操作

第二步:在 VS Code 中安装插件

1. 打开 VS Code
2. 按 Ctrl+Shift+X(Mac 是 Cmd+Shift+X)打开扩展面板
3. 搜索 "GitHub Copilot"
4. 点击 Install
5. 安装完成后,右下角会弹出提示让你登录 GitHub
6. 点击登录,按提示完成授权

第三步:验证是否生效

新建一个文件,随便打一行注释,比如:

// 写一个函数,判断一个数是否是质数

然后按回车,等一两秒,如果 Copilot 开始自动补全灰色的代码,说明安装成功了。


三、核心概念:用大白话讲清楚

在动手之前,有几个概念你得先搞清楚,不然后面用的时候会一头雾水。

3.1 GitHub Copilot 到底是什么

简单来说,Copilot 是一个基于上下文的代码补全工具。它不是"替你写代码",而是"猜你接下来想写什么"。

它的核心能力有三个:

1. 行级补全:你打一行代码,它猜下一行
2. 整函数生成:你写个注释描述需求,它生成整个函数
3. Chat 对话:你可以跟它聊天,问问题、让它解释代码

关键理解:Copilot 的补全质量,高度依赖你给它的上下文。上下文包括:

  • 当前文件的内容
  • 你打开的其他 tab 页的文件
  • 函数名、变量名、注释内容

所以,写好注释和命名好变量,是使用 Copilot 最重要的技能。这一点我当初学的时候完全没意识到,后来才发现,注释写得好的同事,Copilot 用出来效果就是不一样。

3.2 AI搜索 vs 传统搜索

对比维度 传统搜索(Google/Bing) AI搜索(Perplexity等)
结果形式 一堆链接,自己点进去看 直接给出总结性回答,附带引用来源
适合场景 找具体文档、API 参考 快速了解一个概念、做技术选型对比
信息准确度 取决于你找到的网页质量 可能有幻觉,需要验证
交互方式 输入关键词,看结果 可以用自然语言提问,可以追问

我的使用原则

- 需要精确的 API 用法、官方文档 → 传统搜索 + 直接看官方文档
- 需要快速了解一个概念、做方案对比 → AI搜索
- 需要解决具体报错 → 先把报错信息丢给 Copilot Chat,不行再搜索

3.3 什么是"幻觉"(Hallucination)

这是你用 AI 工具一定会遇到的问题,必须提前知道。

幻觉指的是:AI 工具会一本正经地胡说八道。比如:

  • Copilot 给你补全了一个函数,看起来完全正确,但用了一个根本不存在的 API
  • AI搜索告诉你某个库的用法,但实际上那个用法在三年前就被废弃了

我当初就吃过这个亏。Copilot 给我生成了一个数据库查询的代码,我直接 copy 到项目里,跑起来报错了。排查了半天才发现,它用了一个不存在的 ORM 方法。

应对策略

1. AI 生成的代码,永远不要直接信任,一定要 review
2. 遇到不确定的 API,去官方文档验证
3. 让 AI 给出信息来源(AI搜索工具一般会自动给)
4. 对于关键逻辑,自己手写一遍加深理解

四、实战项目:用 AI 工具链做一个 Todo API

光说不练假把式。接下来我们做一个小项目:用 Node.js + Express 写一个 Todo 待办事项的 REST API

整个过程中,我会展示怎么合理使用 Copilot 和 AI搜索,以及在哪里需要特别小心。

4.1 项目初始化

打开终端,执行以下命令:

mkdir todo-api
cd todo-api
npm init -y
npm install express
npm install --save-dev nodemon

然后在 package.json 里加上启动脚本:

{
  "scripts": {
    "dev": "nodemon src/index.js"
  }
}

创建项目目录结构:

todo-api/
├── src/
│   ├── index.js        # 入口文件
│   ├── routes/
│   │   └── todos.js    # 路由定义
│   ├── data/
│   │   └── store.js    # 数据存储(内存版)
│   └── middleware/
│       └── validate.js # 参数校验中间件
├── package.json
└── README.md

4.2 第一步:用 Copilot 生成数据存储层

打开 src/data/store.js,先写一段注释描述你想要的功能:

// 数据存储模块
// 使用内存数组存储 todo 数据
// 提供以下方法:
// - getAll(): 获取所有 todo
// - getById(id): 根据 id 获取单个 todo
// - create(todo): 创建新的 todo
// - update(id, data): 更新 todo
// - delete(id): 删除 todo

写完这段注释后,按回车,等 Copilot 补全。它大概率会生成类似这样的代码:

let todos = [];
let nextId = 1;

function getAll() {
  return todos;
}

function getById(id) {
  return todos.find(todo => todo.id === id);
}

function create(todo) {
  const newTodo = {
    id: nextId++,
    title: todo.title,
    completed: false,
    createdAt: new Date().toISOString()
  };
  todos.push(newTodo);
  return newTodo;
}

function update(id, data) {
  const index = todos.findIndex(todo => todo.id === id);
  if (index === -1) return null;
  todos[index] = { ...todos[index], ...data };
  return todos[index];
}

function deleteById(id) {
  const index = todos.findIndex(todo => todo.id === id);
  if (index === -1) return false;
  todos.splice(index, 1);
  return true;
}

module.exports = {
  getAll,
  getById,
  create,
  update,
  delete: deleteById
};

这里有个坑要注意:Copilot 生成的代码里,delete 是 JavaScript 的保留字,直接作为对象属性导出可能会有问题。它用了 delete: deleteById 这种写法来规避,这是对的。但如果你不注意,直接写 delete 作为函数名,后面调用的时候会出问题。

4.3 第二步:用 Copilot Chat 辅助写路由

打开 src/routes/todos.js,这次我们换个用法——用 Copilot Chat 来辅助。

Ctrl+Shift+I(或者点击侧边栏的 Copilot Chat 图标),输入以下提示:

帮我用 Express 写一个 REST API 路由模块,操作 todo 数据。
需要以下接口:
- GET /todos - 获取所有 todo
- GET /todos/:id - 获取单个 todo
- POST /todos - 创建 todo(需要 title 字段)
- PUT /todos/:id - 更新 todo
- DELETE /todos/:id - 删除 todo
数据存储使用 require('../data/store') 模块

Copilot Chat 会生成一段完整的路由代码。你可以直接采纳,也可以逐条审查后采纳。

我的建议:对于这种结构化的代码,可以让 AI 生成,但你要逐行看一遍,确认:

  1. 路由路径是否正确
  2. HTTP 方法是否正确(GET/POST/PUT/DELETE)
  3. 错误处理是否完善
  4. 状态码是否合理

下面是我审查后调整的最终版本:

const express = require('express');
const router = express.Router();
const store = require('../data/store');

// 获取所有 todo
router.get('/', (req, res) => {
  const todos = store.getAll();
  res.json({ success: true, data: todos });
});

// 获取单个 todo
router.get('/:id', (req, res) => {
  const id = parseInt(req.params.id);
  const todo = store.getById(id);
  
  if (!todo) {
    return res.status(404).json({ 
      success: false, 
      message: 'Todo not found' 
    });
  }
  
  res.json({ success: true, data: todo });
});

// 创建 todo
router.post('/', (req, res) => {
  const { title } = req.body;
  
  if (!title || title.trim() === '') {
    return res.status(400).json({ 
      success: false, 
      message: 'Title is required' 
    });
  }
  
  const newTodo = store.create({ title: title.trim() });
  res.status(201).json({ success: true, data: newTodo });
});

// 更新 todo
router.put('/:id', (req, res) => {
  const id = parseInt(req.params.id);
  const updated = store.update(id, req.body);
  
  if (!updated) {
    return res.status(404).json({ 
      success: false, 
      message: 'Todo not found' 
    });
  }
  
  res.json({ success: true, data: updated });
});

// 删除 todo
router.delete('/:id', (req, res) => {
  const id = parseInt(req.params.id);
  const deleted = store.delete(id);
  
  if (!deleted) {
    return res.status(404).json({ 
      success: false, 
      message: 'Todo not found' 
    });
  }
  
  res.json({ success: true, message: 'Todo deleted' });
});

module.exports = router;

4.4 第三步:用 AI搜索 做技术选型决策

项目中我们需要一个参数校验中间件。这时候可以问问 AI搜索:

问题:Express.js 项目中,轻量级的请求参数校验库有哪些?
请对比 express-validator、joi、yup 这三个库的优缺点。

AI搜索会给你一个对比总结,大概长这样(我简化了一下):

库名 优点 缺点 适合场景
express-validator 与 Express 深度集成,支持链式调用 API 较复杂,学习曲线陡 Express 项目专用
joi 功能强大,社区活跃,文档好 包体积较大 通用场景,复杂校验
yup API 简洁,支持 TypeScript 好 社区比 joi 小一些 配合 Formik 等表单库

但这里有个坑:AI搜索给你的信息可能不是最新的。比如它可能推荐了某个库的旧版本用法。所以我的做法是:

1. AI搜索给出候选方案
2. 去 npm 官网查看各库的最新版本、下载量、维护状态
3. 去 GitHub 看最近一次提交时间
4. 最终做决策

在这个项目里,我们选择自己手写一个简单的校验中间件,因为需求不复杂:

// src/middleware/validate.js
function validateCreateTodo(req, res, next) {
  const { title } = req.body;
  
  if (!title) {
    return res.status(400).json({
      success: false,
      message: 'Validation failed',
      errors: ['Title is required']
    });
  }
  
  if (typeof title !== 'string') {
    return res.status(400).json({
      success: false,
      message: 'Validation failed',
      errors: ['Title must be a string']
    });
  }
  
  if (title.trim().length < 2) {
    return res.status(400).json({
      success: false,
      message: 'Validation failed',
      errors: ['Title must be at least 2 characters']
    });
  }
  
  next();
}

module.exports = { validateCreateTodo };

4.5 第四步:组装入口文件

最后写 src/index.js

const express = require('express');
const todosRouter = require('./routes/todos');

const app = express();
const PORT = process.env.PORT || 3000;

// 中间件:解析 JSON 请求体
app.use(express.json());

// 路由
app.use('/todos', todosRouter);

// 健康检查
app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

// 404 处理
app.use((req, res) => {
  res.status(404).json({ 
    success: false, 
    message: 'Route not found' 
  });
});

// 全局错误处理
app.use((err, req, res, next) => {
  console.error('Unhandled error:', err);
  res.status(500).json({ 
    success: false, 
    message: 'Internal server error' 
  });
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

4.6 运行和测试

启动项目:

npm run dev

用 curl 测试几个接口:

# 创建 todo
curl -X POST http://localhost:3000/todos \
  -H "Content-Type: application/json" \
  -d '{"title": "学习 GitHub Copilot"}'

# 获取所有 todo
curl http://localhost:3000/todos

# 更新 todo
curl -X PUT http://localhost:3000/todos/1 \
  -H "Content-Type: application/json" \
  -d '{"completed": true}'

# 删除 todo
curl -X DELETE http://localhost:3000/todos/1

五、踩坑实录:我们团队总结的 AI 工具使用经验

这部分是整篇文章最有价值的内容,都是真金白银换来的教训。

5.1 Copilot 的上下文窗口限制

现象:你让 Copilot 生成一个复杂函数,它生成的代码引用了文件上半部分定义的变量,但那个变量其实在另一个文件里。

原因:Copilot 的上下文窗口是有限的。它主要看当前文件和少量打开的 tab,不会自动去读你项目里的所有文件。

解决方案

1. 需要引用其他文件的逻辑时,手动把相关文件的 tab 打开
2. 在注释里明确说明依赖关系,比如 "// 使用 ./utils/format.js 中的 formatDate 函数"
3. 对于跨文件的复杂逻辑,不要指望 Copilot 一次生成对,分步来

5.2 AI搜索的信息时效性问题

现象:AI搜索告诉你某个 API 的用法,但你用的时候发现已经被废弃了。

真实案例:我们有个新人用 AI搜索查 React 的用法,结果搜到了 Class Component 的写法,而项目用的是 Functional Component + Hooks。

解决方案

1. AI搜索的结果,一定要标注时间——是2024年的回答还是2020年的?
2. 对于框架和库的用法,优先看官方文档
3. 在提问时加上版本信息,比如 "React 18 中如何使用 useEffect?"
4. 用 AI搜索做"方向性"判断,用官方文档做"精确性"确认

5.3 过度依赖导致的"理解空洞"

现象:新人用 Copilot 生成了一大段代码,跑通了,但问他这段代码什么意思,说不出来。

这个问题很严重。我当初带的一个应届生,用 Copilot 写了一个月的代码,结果让他独立写一个简单功能时,完全不知道从哪下手。因为他已经习惯了"让 AI 帮我写",自己丧失了"从零构建"的能力。

解决方案

1. 新手阶段(前3个月),限制 Copilot 的使用——先自己写,写不出来再问 AI
2. AI 生成的代码,必须能逐行解释清楚才能提交
3. 每周安排一次"无 AI 编程"练习,手写核心逻辑
4. Code review 时,重点问"为什么这么写"而不是"能不能跑"

5.4 安全风险:AI 生成的代码可能有漏洞

现象:Copilot 生成的代码里,没有做输入校验、没有处理 SQL 注入、没有做权限检查。

真实案例:Copilot 给我们生成了一段用户登录的代码,里面密码是明文存储的。如果我们没注意到,直接上线,就是重大安全事故。

解决方案

1. 所有涉及安全的代码(认证、授权、加密、输入校验),必须人工 review
2. 不要盲目信任 AI 生成的安全相关代码
3. 使用专业的安全扫描工具做二次检查
4. 建立团队的安全编码规范,AI 生成的代码也要符合规范

六、常见问题解答

Q1:Copilot 收费吗?学生能用吗?

Copilot 个人版大约 $10/月。但如果你是学生或者开源项目维护者,可以申请免费使用。去 https://github.com/education 申请学生认证即可。

Q2:Copilot 支持中文注释吗?

支持,但效果不如英文。我的建议是:

- 简单的注释可以用中文
- 给 Copilot 的"提示性注释"(用来引导它生成代码的),尽量用英文
- 英文注释生成的代码质量明显更高

Q3:AI搜索和 Copilot Chat 有什么区别?

对比维度 Copilot Chat AI搜索(Perplexity等)
上下文 知道你当前在写什么代码 不知道你的代码
适合场景 解释代码、生成代码、调试报错 技术调研、概念理解、方案对比
信息范围 主要基于训练数据 可以联网搜索最新信息
使用方式 在编辑器内,随手问 打开网页,单独使用

Q4:用了 AI 工具,还需要学基础吗?

需要,而且更需要。

AI 工具是放大器——它放大你的能力。如果你基础好,它能让你效率翻倍;如果你基础差,它只会让你更快地写出有 bug 的代码。

我见过基础扎实的同学用 Copilot,一天能干完以前三天的活;也见过基础差的同学用 Copilot,写出来的代码自己都看不懂,出了问题完全不知道怎么排查。

Q5:怎么判断 AI 生成的代码质量好不好?

我总结了一个简单的检查清单:

□ 代码能跑通吗?
□ 逻辑是正确的吗?(对照需求逐条检查)
□ 有没有用不存在或已废弃的 API?
□ 错误处理完善吗?
□ 有安全隐患吗?(输入校验、权限检查等)
□ 代码风格跟项目一致吗?
□ 能解释清楚每一行在干什么吗?

全部打勾,才能放心提交。


七、学习建议:下一步怎么走

如果你跟着这篇文章走完了整个流程,恭喜你,你已经迈出了 AI 辅助编程的第一步。接下来我给你一些建议:

7.1 短期(1-3个月)

1. 把 Copilot 融入日常开发,但要"有意识地用"
   - 每次它生成代码,停下来想一想:它为什么这么写?
   - 如果它的写法跟你不一样,想想哪种更好

2. 养成"先思考,再问 AI"的习惯
   - 遇到问题,先自己想5分钟
   - 想不出来,再问 Copilot 或 AI搜索
   - 得到答案后,理解它,而不是直接 copy

3. 多读优秀源码
   - AI 能帮你写代码,但"什么是好代码"需要你通过阅读来建立品味
   - 推荐读:Express、Koa、Axios 等库的源码

7.2 中期(3-6个月)

1. 学会写好的 Prompt
   - 给 Copilot 的注释越清晰,生成的代码质量越高
   - 给 AI搜索的问题越具体,得到的答案越有用
   - 这本身就是一种需要练习的技能

2. 建立自己的"AI 使用规范"
   - 哪些场景适合用 AI?
   - 哪些场景必须手写?
   - 怎么验证 AI 的输出?

3. 尝试用 AI 做更大规模的项目
   - 比如一个完整的前后端项目
   - 体验 AI 在复杂项目中的能力和局限

7.3 长期(6个月以上)

1. 关注 AI 编程工具的最新进展
   - 这个领域发展极快,每隔几个月就有新工具出来
   - 保持开放心态,但不要被工具牵着走

2. 深耕你的专业领域
   - AI 是工具,你的核心竞争力是对业务的理解、对架构的把握、对问题的判断
   - 这些是 AI 短期内替代不了的

3. 参与开源社区
   - 看看别人怎么用 AI 工具
   - 分享你自己的经验
   - 教学相长

八、写在最后

我写这篇文章的初衷,是因为我看到太多新人把 AI 工具当成"救命稻草"——遇到任何问题都先问 AI,拿到答案就直接用,完全不过脑子。

这样做短期看确实效率高,但长期来看,你是在用"未来的自己"换"现在的效率"。

AI 工具是好东西,GitHub Copilot 和 AI搜索确实能大幅提升开发效率。但前提是——你得先有能力判断它给你的东西是对是错

我当初学编程的时候,没有这些工具,所有东西都得自己查、自己试、自己踩坑。过程很痛苦,但基本功就是这么打下来的。

现在你们有了更好的工具,这是好事。但别让工具成了你的拐杖,而要让它成为你的翅膀。

记住这个原则

AI 负责"快",你负责"对"。
AI 负责"生成",你负责"判断"。
AI 负责"执行",你负责"思考"。

好了,这篇文章就到这里。如果对你有帮助,欢迎分享给身边刚开始学编程的朋友。我们下篇文章见。

评论 0

最热最新
暂无评论
威武山峰Lv.1
0
影响力
0
文章
0
粉丝