用AI写代码的人越来越多,但写出来的代码质量参差不齐。问题往往不在AI,而在你怎么跟它"说话"。一个好的Prompt能让AI输出专业级代码,一个模糊的Prompt只会得到一堆需要返工的半成品。本文系统梳理AI编程场景下的Prompt工程技巧,帮你真正把AI用好。
为什么Prompt这么重要
很多人用AI写代码的体验是这样的:
"帮我写一个用户登录功能"
AI洋洋洒洒写了两百行,结果:用了你不需要的框架、没做输入验证、密码直接明文存储、跟你的项目架构完全不搭。
然后你花半小时修修补补,还不如自己从头写。
问题出在哪? 不是AI不行,而是你给的信息太少。AI只能根据你提供的上下文来"猜"你想要什么。Prompt的本质就是消除歧义、缩小搜索空间。
模糊 Prompt → AI 猜测 → 大量返工
精准 Prompt → AI 精确生成 → 微调即用
Prompt的五层信息模型
一个好的编程Prompt应该包含五个层次的信息:
| 层次 | 内容 | 示例 |
|---|---|---|
| 角色 | 期望AI扮演什么角色 | "你是一个资深Go后端工程师" |
| 任务 | 具体要做什么 | "实现一个JWT中间件" |
| 约束 | 技术栈、风格、限制 | "使用gin框架,不引入第三方JWT库" |
| 上下文 | 项目背景、已有代码 | "现有项目结构如下..." |
| 输出格式 | 期望的输出形式 | "给出完整代码+单元测试+使用说明" |
不需要每次都写满五层,但信息越完整,结果越精准。
反面教材 vs 正面示范
场景一:写一个工具函数
反面:
帮我写一个日期格式化函数
AI可能会用你项目里根本不存在的库,写出跟你项目风格完全不同的代码。
正面:
用Go写一个日期格式化函数,要求:
- 输入是time.Time和格式字符串
- 支持"2006-01-02"、"2006/01/02 15:04:05"两种预定义格式
- 输入零值时返回空字符串而非报错
- 放在项目已有的 utils/time.go 中,与现有函数风格一致
- 附上表驱动测试
场景二:修复Bug
反面:
这段代码有bug,帮我修一下
正面:
以下Go代码在并发场景下偶发panic: runtime error: concurrent map writes。
复现路径:10个goroutine同时调用ProcessOrder()。
我的分析是orders map没有加锁保护,请确认并修复。
修复时注意:不要引入全局锁,考虑用sync.Map或分片锁。
[粘贴代码]
场景三:代码重构
反面:
优化这段代码
正面:
重构以下代码,目标:
1. 提取重复的数据库查询逻辑为独立方法
2. 将硬编码的SQL改为参数化查询
3. 保持所有现有测试通过
4. 遵循项目现有的Repository模式
5. 不要改变公开API的签名
[粘贴代码]
六大核心Prompt技巧
1. 提供示例(Few-Shot)
给AI看你想要的代码风格,比说一百句"风格要好"都管用:
按照以下风格为PaymentService写单元测试:
// 已有测试示例
func TestUserService_CreateUser_Success(t *testing.T) {
svc := NewUserService(mockRepo, mockLogger)
user, err := svc.CreateUser(context.Background(), CreateUserReq{
Name: "Alice",
Email: "alice@example.com",
})
require.NoError(t, err)
assert.Equal(t, "Alice", user.Name)
mockRepo.AssertCalled(t, "Insert", mock.Anything)
}
请为PaymentService.ProcessPayment写类似风格的测试,覆盖:
- 支付成功
- 余额不足
- 网络超时
2. 分步拆解(Chain of Thought)
复杂任务不要一步到位,让AI分步思考:
我需要实现一个分布式限流器。请按以下步骤进行:
第一步:分析需求——每秒最多1000次请求,部署在5个节点上,需要精确限流
第二步:选型——对比令牌桶、滑动窗口、固定窗口三种算法,给出推荐
第三步:设计接口——定义RateLimiter的公开方法签名
第四步:实现核心逻辑——用Go实现选定的算法
第五步:写测试——覆盖正常限流、边界值、并发安全
每一步完成后暂停,等我确认再继续。
3. 指定约束条件
约束越明确,AI越不容易跑偏:
用Python实现一个配置加载器,约束条件:
- Python 3.10+,不使用任何第三方依赖(仅标准库)
- 支持JSON和YAML格式(YAML用简单正则解析,不引入PyYAML)
- 支持环境变量覆盖:ENV_VAR_NAME 覆盖 config.key.name
- 配置值支持类型自动推断(int/float/bool/string)
- 文件不存在时使用默认配置,不抛异常
- 代码不超过150行
4. 利用上下文窗口
把相关代码贴给AI,让它理解项目全貌:
以下是我项目的目录结构和关键接口定义:
[目录结构]
[interfaces.go 内容]
[现有的 user_service.go 内容]
现在请按照相同的模式实现 order_service.go,保持一致的:
- 错误处理风格(自定义Error类型)
- 日志记录方式(slog)
- 依赖注入方式(构造函数参数)
- 测试结构(表驱动 + testify)
5. 反向验证
让AI在生成代码后自己检查:
实现完成后,请:
1. 列出这段代码可能存在的3个边界条件问题
2. 检查是否有并发安全隐患
3. 评估时间复杂度和空间复杂度
4. 如果有问题,直接修复并说明修改了什么
6. 迭代优化
不要期望一次Prompt就完美,学会迭代:
第一轮:生成基础实现
→ "代码可以工作,但错误处理太粗糙,请为每个错误路径添加结构化日志和错误码"
第二轮:增强健壮性
→ "补充单元测试,重点覆盖错误路径和边界条件"
第三轮:补充测试
→ "检查代码中是否有可以提取为公共方法重复逻辑"
第四轮:重构优化
不同场景的Prompt模板
新功能开发
在[项目/模块]中实现[功能描述]。
技术栈:[语言+框架+版本]
已有接口:[粘贴相关接口定义]
设计要求:
- [功能点1]
- [功能点2]
- [异常处理策略]
- [性能要求]
输出要求:
- 完整可运行的代码
- 单元测试覆盖核心逻辑
- 关键决策的注释说明
Bug修复
Bug描述:[具体现象]
复现步骤:[1. 2. 3.]
期望行为:[应该怎样]
实际行为:[实际怎样]
环境:[OS/语言版本/框架版本]
相关代码:
[粘贴代码]
请:
1. 分析根因
2. 给出修复方案
3. 实现修复代码
4. 编写回归测试确保不再复现
代码审查
请审查以下代码,关注:
1. 安全漏洞(注入、越权、敏感信息泄露)
2. 并发安全(竞态条件、死锁)
3. 错误处理(是否有被吞掉的错误)
4. 性能问题(N+1查询、不必要的内存分配)
5. 可维护性(命名、职责划分、代码重复)
按严重程度从高到低排列问题,每个问题给出:
- 问题描述
- 具体位置(行号或代码片段)
- 修复建议(附代码)
[粘贴代码]
API设计
设计一个[功能]的RESTful API,要求:
- 遵循RESTful规范和项目现有API风格
- 给出每个接口的:方法、路径、请求体、响应体、状态码
- 包含错误响应格式(统一错误码)
- 考虑分页、过滤、排序
- 给出OpenAPI 3.0规范
现有API风格参考:
[粘贴一个现有API的示例]
进阶技巧
让AI扮演审查者
你是一位有10年经验的后端架构师。请审查我的实现,重点检查:
- 是否遵循SOLID原则
- 是否有过度设计或设计不足
- 异常处理是否完整
- 是否考虑了可观测性(日志、指标、追踪)
[粘贴代码]
利用否定指令
告诉AI不要做什么和告诉它要做什么一样重要:
实现用户注册功能,注意:
- 不要使用ORM,用原生SQL
- 不要引入新的第三方依赖
- 不要修改现有的数据库schema
- 不要在handler层直接操作数据库
- 不要返回完整的用户对象给前端(脱敏处理)
对比方案
我需要实现一个任务队列。请对比以下三种方案的优劣:
1. 基于Redis List + BRPOP
2. 基于PostgreSQL SKIP LOCKED
3. 基于NATS JetStream
评估维度:吞吐量、持久化、复杂度、运维成本、团队学习曲线。
我的项目背景:Go语言,日均任务量约50万,已有Redis和PostgreSQL基础设施。
给出你的推荐和理由。
生成文档和注释
为以下代码生成:
1. 函数级别的godoc注释(遵循Go文档规范)
2. 复杂逻辑的行内注释(解释Why,不解释What)
3. 一个使用示例(Example函数格式)
不要为显而易见的代码加注释。
[粘贴代码]
常见误区
误区一:Prompt越长越好
错。过长的Prompt会稀释重点信息。关键是把约束条件和上下文给清楚,而不是堆砌废话。
误区二:一次Prompt搞定一切
错。复杂任务应该拆分为多轮对话。第一轮搭框架,第二轮补细节,第三轮做优化。每次让AI聚焦一件事。
误区三:完全信任AI的输出
错。AI生成的代码必须经过审查。特别关注:
- 安全问题(AI经常忽略)
- 并发安全(AI倾向于写单线程代码)
- 错误处理(AI经常吞掉错误或用panic代替)
- 第三方依赖版本(AI可能用过时API)
误区四:不给项目上下文
错。AI不了解你的项目。把目录结构、接口定义、编码规范贴给它,结果会好一个量级。
误区五:用自然语言描述代码结构
错。直接贴代码比用文字描述"有一个UserServiceImpl类继承了BaseService..."高效得多。
工具链配合
Prompt工程不是孤立的,配合工具效果更好:
| 工具 | 配合方式 |
|---|---|
| Cursor / Qoder | 自动加载项目上下文,减少手动粘贴 |
| Copilot Chat | 选中代码直接提问,上下文自动带入 |
| Claude Code | 终端Agent模式,自动读取项目文件 |
| 自定义系统Prompt | 预设项目规范,所有对话自动继承 |
设置项目级系统Prompt
很多工具支持项目级别的系统Prompt(如Cursor的.cursorrules),可以预设:
你是一个Go后端工程师,项目技术栈:
- Go 1.22 + Gin + sqlc + slog
- 遵循项目现有的分层架构:handler → service → repository
- 错误处理使用自定义AppError类型
- 所有公开方法必须有单元测试
- 日志使用结构化日志,包含trace_id
- 不使用全局变量,依赖通过构造函数注入
这样每次对话都自动继承这些约束,不用反复说明。
总结
AI编程的Prompt工程,本质是把隐性知识显性化的过程。
你脑子里有很多"理所当然"的约束——项目风格、技术选型、编码规范、异常处理策略——这些信息AI不知道。Prompt的作用就是把这些信息传递给AI。
记住这个公式:
好的Prompt = 明确的任务 + 充分的约束 + 相关的上下文 + 期望的输出格式
不需要每次都写得很长,但要养成多给一句约束的习惯。多一句"不要用ORM",就能避免AI引入你不想要的依赖;多一句"保持测试通过",就能避免AI破坏现有功能。
从今天开始,别再让AI猜了。