ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI辅助Golang商业项目实战:59篇日志沉淀的协作心法

AI辅助Golang商业项目实战:59篇日志沉淀的协作心法 说实话这个项目收工那天我坐在电脑前翻了一遍这两个月的59篇开发日志心里最大的感触不是“终于写完了”而是“我一开始用AI的方式基本上全错了”。当时接这个Golang商业级项目的时候我给自己定的规矩是“每天至少记录一篇日志”原意只是想把进度留痕方便客户和周会汇报。但到项目中期日志变成了我梳理AI协作方式的主要工具——哪些地方AI真的帮我省了时间哪些地方它反而制造了更多麻烦哪些提示词策略在真实业务压力下根本不成立全被记录在案。这篇文章是下篇。上篇我聊了聊AI编码的选型逻辑和整体工作流这篇我打算把这些日志里沉淀下来的使用心法全部摊开讲包括AI生成Go代码的边界在哪里、Golang项目里上下文该怎么管理、商业级项目的质量关卡怎么设以及我对AI辅助开发这件事的最终判断。如果你正打算用AI扛一个有点分量的项目而不是写写Demo这篇文章应该能帮你少走很多弯路。1. 59篇日志背后我如何用AI重构了Golang项目的开发节奏先说一个反直觉的结论AI真正改变的不是我的编码速度而是任务的拆解方式。以前写Go项目我的习惯是拿到需求之后直接开干边写边理结构遇到问题了再回头改。但这个项目的体量不允许这种“边写边想”的模式涉及多个服务模块、权限体系、第三方支付对接每一步都牵连很广。AI介入之后我发现一个特别重要的变化——它逼着我把任务拆到足够小因为只有足够小的任务AI给的代码才是可靠的。1.1 日志机制如何变成了“AI协作的节拍器”我最初写日志只是为了记录进度后来它意外承担了一个关键功能每天开工前我先翻前一天的日志把当前任务重新说清楚再决定今天的任务切片。这个“重新说清楚”的过程实际上就是给AI喂上下文的过程。具体操作是这样的每天的任务日志里我会包含三个固定段落——“当前模块状态”、“今日目标”、“昨日遗留问题”。到了第二天我直接把这三段粘给AI再配合相关的接口定义或数据结构让它先复述一遍我的意图再开始写代码。如果它复述错了说明我对任务的定义本身不清晰先修任务描述再让它动手。这个习惯帮我避免了一项巨大浪费AI生成了100行代码结果方向不对全部推倒重来。在Golang项目里方向性错误尤其昂贵因为接口一旦定型后面的service、repository、handler全都跟着接口走。如果接口定义错了AI生成的每一层都是在错误的地基上盖楼。1.2 从“让AI写码”到“让AI帮我想方案”日志记录到第三周的时候我发现一个特别明显的变化我让AI直接写代码的次数变少了让它给我出方案A和方案B对比的次数变多了。举一个具体的例子。项目里需要实现一个多租户数据隔离的方案我当时有两种想法一种是用独立的PostgreSQL schema做隔离另一种是给每张业务表加tenant_id字段做行级隔离。这两条路在Golang项目里的落地点差别非常大——前者意味着数据库连接池管理、schema动态切换、GORM的回调钩子都要重新设计后者虽然简单但查询业务代码里到处都要记得加租户条件漏一个就是个生产事故。我当时的处理方式现在回头看很值得分享我把两种方案的相关背景包括项目的并发量预估、数据库规模、团队规模、后续运维能力全部丢给AI让它基于这些上下文做利弊分析。它给出来的答案其实和我自己的判断差不多但这不重要。重要的是我在这个过程中被迫把方案的边界条件一条条写清楚这本身就是一个非常高效的思考过程。日志里那一天的记录我记得很清楚写的是“AI没有告诉我不知道的东西但它逼我把知道的东西系统化地讲出来。”这也是我最想强调的一点AI使用心法的核心不是把AI当成一个更聪明的助手而是把它当成一面能映照你思考漏洞的镜子。你以为自己早就想清楚的事情在试图让AI复述一遍的时候才发现根本没办法讲顺。这不是AI的问题是你自己的问题。而日志就是捕捉这种问题的最佳工具。2. 让AI写Go代码先搞清楚它的边界在哪里在我这两个月的实践里AI写Go代码的能力有很明显的分层。不同性质的代码AI的表现天差地别。搞清楚这个分层会让你在选择“让AI写”还是“自己写”的时候有一个非常清晰的判断依据。2.1 三类AI能写好的代码样板、CRUD、标准库我总结下来AI写Golang代码最靠谱的领域有三类。第一类是接口实现和样板代码。比如你给它一个接口定义让它生成对应的结构体方法或者给它一套HTTP handler的框架代码让它补全参数绑定和错误处理。这类代码模式固定规则明确AI生成的质量相当稳定。我的经验是先定义好接口让AI按接口写实现而不是直接描述功能。接口本身就是最强的约束条件有了约束AI的自由发挥空间就小了出错概率也直线下降。第二类是CRUD相关的代码。GORM的链式调用、基础查询、分页逻辑、简单的关联查询这些在训练数据里出现的频率极高AI处理起来很顺手。但注意我用了“简单”这个词。一旦涉及复杂的关联查询、嵌套预加载、事务边界控制AI的失误率就开始上升。它的失误不是语法层面的而是逻辑层面的——它会把业务规则悄悄简化导致查询结果和业务预期不一致。第三类是标准库相关的问题。AI对于Golang标准库的掌握程度相当好time、context、sync、encoding/json、net/http这些包的用法它给出的代码几乎不用改。特别是context的超时控制和传递链稍微描述清楚场景AI写出来的东西就能直接进代码库。这和框架代码不同——框架API变化快训练数据里容易混入过时的用法但标准库十分稳定AI见过的样本量又大可信度很高。2.2 高并发与并发安全的Go代码AI只能辅助不能主导接下来这段话我写得很慎重因为它是这个项目里最血淋淋的经验AI写不了高并发场景下的核心逻辑至少写不了可以直接上生产环境的并发代码。我们项目里有一个任务调度的模块涉及多个worker并发消费任务队列需要精确控制任务的幂等性、并发上限和失败重试。我试过让AI直接写这段逻辑的调度核心它写出来的版本在常规测试中完全正常单看代码结构甚至很漂亮——用channel来分配任务用sync.WaitGroup来管理生命周期整个设计看起来非常规整。但压测之后问题全冒出来了任务重复消费的场景没有充分覆盖context取消之后goroutine没有全部退出select的分支优先级在极端情况下会选错路径。问题不在于AI不会写并发代码而在于并发代码的正确性是靠极端场景逼出来的不是靠代码范式和设计模式推出来的。AI见过很多并发模式但它不知道你的业务系统里什么样的极端场景可能发生。goroutine泄漏、死锁、数据竞争这些问题只有真正理解了业务逻辑之后才能提前预防。AI写出来的并发代码至少要在你脑子里跑一遍完整的极端场景推演确认没有问题之后才能进代码库。我的处理方式是并发调度框架自己搭AI只负责填没有并发隐患的细枝末节比如某个独立的事件处理函数、某个不涉及状态共享的工具函数。这种分工看起来很保守但收益非常稳定代码Review的工作量控制在一个可控范围内。2.3 编译通过不等于逻辑正确AI代码的隐性盲区这件事我推进系统中间遇过很多次挑最典型的一次说。当时我需要一个导出月度账单报表的功能要求是统计订单金额、退款金额、净收入三个指标。AI很快就生成了一段代码编译通过简单的测试数据也正常。但我仔细读了一遍发现它在计算退款金额的时候直接把退款订单的amount字段取出来了而没有考虑部分退款的情况。这个业务规则是AI用自己“想当然”的规则补上的。这就是AI代码最危险的地方——语法和类型层面它几乎不犯错因为编译器和IDE会兜底但业务逻辑层面它经常自作聪明用统计学上的高频模式去预测它根本不了解的领域规则。商业项目里这类隐性盲区分分钟是生产事故级别的坑。后来我所有的代码Review都会特别关注一件事AI生成代码里所有关于业务规则的假设。如果它隐含着“所有订单都是全额退款”“所有用户只有一个角色”“状态机只按线性流转”这种假设我全部要揪出来一条条对照需求文档验证。这个过程很累但我可以确定地说不这么做的话用AI辅助开发商业项目的风险是不可控的。3. 上下文管理才是AI辅助开发的真正分水岭这个话题几乎没人认真聊过但我在项目里花了最多时间的就是它。AI写代码写得好不好七成取决于你给它喂的上下文三成取决于任务本身的难度。大多数人把注意力放在怎么描述任务上却忽略了一个更底层的问题你做Golang项目的时候到底应该给AI喂什么上下文喂多少合适3.1 全套代码库塞进去不是良策反而适得其反我刚启动项目那两周犯过一个典型的错误以为AI知道的信息越多产出的代码越准确所以每次提问都疯狂地贴上下文。把项目的目录结构、所有接口定义、核心数据模型一股脑地粘上去用长上下文硬聊。结果模块小的时候还好模块一多AI就开始糊涂了——它会混淆不同模块里的同名类型会把服务A的数据结构用到服务B的代码里。后来我换了一种思路开始做减法。每次提问之前先问自己一个问题AI写这段代码最需要知道的最小信息集是什么然后只投喂这些信息。比如让AI写一个订单模块的repository我需要给它的是订单表结构、订单状态枚举、以及它要使用的数据访问模式别的都不需要。上下文越精准AI的输出越可控这个规律在Golang项目里尤其明显。3.2 Golang项目的三种上下文单位以及如何组织经过这两个月的反复折腾我把Golang项目的上下文组织成了三个单位。第一个单位是类型定义。Golang是一门强类型语言类型就是最好的约束。让AI写代码之前先把相关的struct定义给它包括字段名、字段类型、json tag。这样做有两个好处一是AI生成的代码天然合规结构体字段不会再“自由发挥”二是类型本身就是一种隐形的指令AI看到字段名就能推断出代码的逻辑不用你把业务讲得太细。第二个单位是接口约定。如果这段代码要接入某个既有模块把接口签名贴出来再说明数据流动的方向。Golang的接口设计是鸭子类型AI生成的实现类只要能满足接口约束集成问题就解决了一大半。第三个单位是业务规则的显式描述。这部分必须用自然语言写清楚不能指望AI从代码里猜。比如“当订单状态为已取消且退款状态为处理中时不能重复触发退款”。这类规则AI猜不到必须由你显式地告诉它。3.3 一套可复用的Prompt结构我项目后半程的固定套路反复摸索之后我把这套方法固化成了一套Prompt结构项目后半段使用AI的频率大幅提升正确率也稳定了。结构如下背景这里写当前模块的概述包括这个模块在系统中的作用、依赖了哪些其他模块。 类型定义这里贴相关的Go struct定义包含json tag。 接口约定这里贴需要实现的接口签名或需要调用的外部接口。 业务规则这里用条目列出所有需要遵守的业务规则越具体越好。 任务这里用一句话描述需要生成的代码以及输入输出的边界。 验收标准这里列出代码完成后需要满足的条件包括错误处理和边界情况。这套结构的核心思想是把AI当成一个新加入项目的开发它需要的不是信息而是结构化、无歧义的指令。我发现一个问题当AI出错的时候百分之八十的情况不是它笨而是它不知道边界条件在哪里或者说它被训练成了一个“总是补充缺失假设”的模型。如果你不显式地告诉它边界条件它就自己编一个。Golang项目的商业代码经不起这种“编造”所以必须从上下文的组织上杜绝这种可能性。4. 商业级项目的代码质量关卡AI输出必须经过的几道阀门先摆一个我的结论用AI写代码这件事在小项目和个人项目里你完全可以信任它的输出但到了商业级项目里你必须假设AI的代码是“有能力的实习生写的”——它能独立完成大部分工作但也一定埋着多个让你难以察觉的错误。所以我的工作流里AI产出的代码要经过四道关卡才能合入代码库。4.1 静态分析和单元测试是成本最低的质量底线第一道关卡是工具层面的没有太多讨论空间静态分析加单元测试。代码合入之前golangci-lint必须零告警关键逻辑必须有一组单元测试覆盖。这个原则即使不用AI我本来也会执行但有了AI之后它变得尤其重要——AI生成的代码在风格上很容易踩lint的规则最常见的就是错误处理不规范、没走error wrapping、省略了必要的nil判断。我记得有一次AI生成的代码里有个函数返回了多个值其中一个错误返回值在最深层的分支里被直接return了外层的调用方拿到这个错误之后没有做unwrap就直接判断错误类型结果等于是错的。这类问题在静态分析里会被直接抓出来所以我说这道关卡成本最低因为它不需要你思考只需要你严格执行。4.2 Code Review时重点查看AI代码的三个固定位置工具关卡过了之后就要进入人工Review。带着AI开发之后我Review代码的方式和以前完全不同了。我以前是通读一遍检查逻辑和风格现在我是带着“找茬清单”去Review只看三个固定位置。首先是错误处理分支。AI生成的代码在外面包装的错误处理往往没问题但深层嵌套的错误分支是重灾区。典型的场景是一个函数有多个return err的出口AI可能在某一个出口忘了做错误包装导致调用方拿到的错误信息完全无法定位问题。其次是并发安全相关的位置。AI生成的代码如果涉及共享变量通常不会主动加锁。不是它不知道要加锁而是它在生成这段代码的时候没有意识到这个变量会在另一个goroutine里被修改。所以Review的时候我会问自己一个问题这段代码涉及读写的数据在本函数之外还有没有其他函数在读写如果有那同步机制谁来保证最后是资源释放。涉及打开连接、创建临时文件、初始化资源的地方AI有时候会漏掉清理逻辑或者defer的位置写错了导致资源长期占用不释放。这类问题在开发环境里几乎不会暴露上了生产之后慢慢累积最后变成诡异的内存增长或连接泄漏。4.3 安全敏感逻辑不能交给AI自由发挥商业级项目和普通项目最大的区别之一就是安全敏感逻辑绝对不允许有任何模糊和想象空间。权限校验、支付签名、密钥管理、用户鉴权、数据越权检查……这些代码我不会让AI“自由发挥”只会让它按照我既定的逻辑和库函数去实现具体步骤。举个例子项目里需要校验一个从第三方支付平台回调过来的签名。这个签名算法是支付平台规定的校验流程也是明确写死的步骤。我让AI在这里做的事只是“按步骤实现”把每一步的输入输出给它讲清楚然后它在框架上填空。我不会让它自己去设计某个防重放机制或者让它猜“签名校验应该用什么加密算法”这类授权看起来小事一桩实际上一旦AI交出来的代码跟业务方的安全约定不一致后果是难以收拾的。给AI套上缰绳明确哪些部分它可以代为执行、哪些部分它只有填空权这比任何提示词技巧都更能保证商业项目的安全边界。控制力是第一位的效率永远排在它后面。根据我的实际操作经验把AI输出的代码当作一项必须接受严格审查的产出比一开始就信任它要高效得多。因为信任建立之后你可能会放松警惕但带着怀疑去Review你才能真正看清它写了什么。5. 两个月的实践给我留下的三条AI使用心法写到这里我已经把项目里关于AI协作的细节讲得差不多了。最后想分享三条超越具体项目的心法它们也是这59篇日志里出现频率最高的三条反思。在任何项目里都可以直接套用这三条心法来检验自己的用法是否走偏至少我的实践证明了它们有效。5.1 让AI先否定你的方案再让它肯定你的方案这是我从项目第二周就一直在用的方法且效果出奇地好。大部分人的习惯是把自己的方案描述给AI然后让它实现我建议反过来先把方案告诉AI让它扮演一个经验丰富的Golang开发者从设计缺陷、边界漏洞、扩展性角度找出方案里的问题。等它挑完毛病你再让它基于这些否定意见给出修正方案。原因很简单大模型的训练数据里有大量的真实代码审查和方案讨论这种“找问题”的任务正是它的优势场景。它没有你作为项目所有者的那种惰性——你已经为自己的方案投入了情绪它反而能站在中立的立场上找出盲点。我做多租户隔离方案的时候AI提出过一个我完全没考虑到的索引设计问题后来在生产数据量上去之后确实变成了一个性能隐患好在当时听了它的建议提前处理了。5.2 只从AI手里接“已经有人写清楚逻辑”的代码这句话是我在日志里对自己说的因为它真的救了我很多次。回顾这个项目里所有真正“一次写对”的AI辅助代码它们都有一个共同特征接手之前逻辑已经被人为梳理过了。我自己写一个复杂函数的时候会先在注释里把几个核心步骤列出来然后让AI按注释填充代码。比如权限校验模块我先写这样一段注释// CheckPermission 检查当前用户是否对指定资源拥有操作权限。 // 执行顺序 // 1. 如果用户是超级管理员直接返回 true。 // 2. 根据 resourceID 获取资源的所属租户。 // 3. 如果用户的租户ID和资源租户ID不一致返回 false。 // 4. 查角色权限表判断当前用户角色是否包含该操作权限。 // 5. 返回最终权限结果。然后让AI照这个注释实现。这种写法的成功率极高因为逻辑的边界和顺序已经明确AI的自由发挥空间被限制到了最小。如果你发现自己没办法先写出这种注释说明你对逻辑的理解还不够清楚这个阶段不建议让AI动手。5.3 一个项目的成功不取决于AI强不强而是取决于你问得好不好这句话听起来很像正确的废话但我的实践体会是问得好这件事本身要拆成很具体的能力。第一个能力是能识别一个问题应该用多大粒度的上下文来描述这个我前面已经讲过了。第二个能力是能在问题描述中区分意图和实现——你要告诉AI你要解决什么问题而不是直接告诉它你准备怎么实现。比如你不能只跟AI说“把这段逻辑改成并发版本”你得说清楚这段逻辑当前的执行方式、哪些操作之间有依赖关系、哪些可以并行、并行的最终结果需要合并成什么形式。AI不是读心术它的输出质量直接反映了你输入信息的质量。两个月项目走完之后我最大的收获其实是AI使用心法的本质就是反思并优化自己的表达能力。项目收工那天下午我把最后几篇日志的通告写完了关掉终端之前又看了一遍项目目录。这个项目从每天被AI生成的代码大小坑到后半程能够比较稳定地产出可靠代码这中间的转折点其实不是某个具体的提示词技巧而是我彻底接受了一个事实——AI给的是可能性不是答案AI生成得再多最终要对业务和生产负责的人仍然是我。也是从那时候开始我才有底气说“AI确实让我这个项目提前收工了但收工的原因不是它写得快而是我们配合的方式对了。”
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进