AI 写的代码,为什么总像"差不多对"?我用 opencode 把 commit 前审查做成三道门

AI 写的代码,为什么总像“差不多对”?我用 opencode 把 commit 前审查做成三道门 我用opencode做代码审查,注重agents.md的质量,聚焦多轮核心BUG输出质量,减少MR被驳回的风险 审查阶段不要使用可写 agent。 可写 agent 看到问题后很容易顺手修复,修复后的代码又变成新的审查对象。我要的是报告,不是未经确认的工作树变化。 AGENTS.md 不是越长越好。 我见过把抽象价值观、编码风格和所有历史事故都塞进去的规则文件,最后 AI 什么都读到了一点,却没有一条真正执行到位。规则应当短、具体、可验证。 不要只统计 AI 提了多少条意见。 我更看重高价值意见的比例、误报率、漏报案例和处理耗时。意见越多不等于审查越好。 我最近在 Go 项目里遇到过一个很典型的例子:我让 AI 把一个用 sync.Mutex 保护的缓存改成 sync.RWMutex,因为读请求远多于写请求。代码能编译,go test -race 也通过了,我正准备提交时又看了一遍 diff,才发现 AI 在 RLock() 之后没有为所有提前返回的分支补上 RUnlock()。原代码用 defer Unlock() 做了一次兜底,锁的种类变了,兜底结构却没有一起变。 这个问题不是函数体“完全写错”,而是局部正确、整体破坏。测试没有触发那个错误分支,竞态检测自然也抓不到。类似的情况我见过很多:错误被 _ 接住、context 半路丢失、goroutine 没有退出条件、异常路径没有补齐、依赖被悄悄换成团队没人维护的库。AI 生成代码的速度越快,diff 的影响半径就越容易被低估。 我现在把 commit 前的审查拆成三道门:机器门负责确定性检查,AI 自审负责挑出候选风险,人工 review 负责业务判断和最终签字。这篇文章记录我在 Go 项目里实践这套流程的方式,也会说明 opencode 适合放在哪一层、哪些事情仍然不能交给它。 蓝色 表示工具或事实,绿色 表示我的实践判断,红色 表示容易踩的坑,黄色 表示可以直接改写到自己项目里的模板。 一、先把 commit 当成一次小型发布 以前我把 git commit 当作保存进度,后来几次线上问题让我改了看法:commit 是把一组行为变化交给团队和环境的发布动作。即使还没有上线,它也已经影响了后续 review、合并、回滚和事故追踪。 ...

2026-08-29 · 4 min · 836 words · FunkyGod

AI 生成代码该怎么审:一套可以直接使用的实操框架

AI 生成代码该怎么审:一套可以直接使用的实操框架 我的核心要求:减少 BUG,减轻 Review 压力,避免生产环境出现不可逆的风险。不要怕对同一个任务开多个agent,重要的是让不同关注点能充分执行,人工做最后的审核兜底; 一、AI 写得越快,审查越不能只看“像不像对的” AI 一分钟可以生成几百行代码,几小时就能跑完一轮 PR 流程。真正决定质量的,已经不只是 AI 写得快不快,而是我们能不能在代码生成之后,用合适的方法把它审干净。我自己每天让 AI 生成大约一半的代码改动,但最后原样合进主干的,大概只有三成。剩下的代码往往不是“完全写错”,而是“看起来很像对”:错误被 _ 接住,权限校验在调用链里悄悄漏掉,并发场景只覆盖了 happy path,或者引入了一套团队没人熟悉的依赖。这些问题可能过得了 lint、单元测试和评审,却会在生产环境里变成真正的事故。 所以,我现在不把 AI 当成“替我批准代码的人”,而是把它放在风险筛查器的位置:先帮我快速找出值得追问的地方,再由作者、人工 Reviewer 和领域负责人作最终判断。这个定位也和公开实践比较一致:OWASP 把人工代码审查定义为对自动化安全测试的补充,重点放在业务逻辑、复杂安全实现和具体上下文上;Google 的评审指南则强调,测试本身也需要人来判断是否真的有效。可参考 OWASP Secure Code Review Cheat Sheet 和 Google 的代码评审实践。 二、先把审查输入准备好,AI 才不会对着空气猜 我以前最容易犯的错,是把一段代码直接丢给 AI,然后补一句“帮我仔细审查”。现在我会先准备一张很短的“审查输入卡”,至少包含下面五项: 目标:这次改动要解决什么问题?不解决什么问题? 不变量:哪些已有行为、权限边界、接口兼容性和数据约束绝对不能被破坏? 范围:本次 PR 改了哪些文件、调用链和配置?哪些内容只是必要上下文? 验证:新增或修改了哪些测试?正常路径、异常路径和回滚路径分别是什么? 风险:是否涉及登录、权限、支付、个人信息、文件上传、数据库迁移、加密或外部依赖? 日常 PR 我会让 AI 以 diff 为主,只补充相关接口、数据结构、配置和测试。OWASP 也把 diff-based review 作为 Pull Request 和日常开发的适用方式;新系统、重大版本、遗留系统接管或事故复盘,才更适合做全量的 baseline review。另一个有效做法是控制 PR 的大小:Google 建议一个变更尽量只做一件自洽的事,相关测试跟着代码一起提交,大型重构与功能修改分开。这样做的收益很直接:AI 看得少而准,人也更容易发现真正的行为变化。 ...

2026-08-26 · 2 min · 228 words · FunkyGod

减少 AI 返工,我现在一般这么做

减少 AI 返工,我现在一般这么做 原文:Review AI-generated code 与 AI 代码审查实践的综合解读 作者:我(结合个人 AI 编程实践整理) 来源:GitHub、Uber、Cloudflare、Trellis 等公开资料,整理于 2026 年 08 月 26 日 AI 写代码越来越快,但返工并没有因此自动消失。我现在更关心的,不是 AI 一次写了多少,而是错误能不能更早暴露、修改能不能更小、人工判断能不能用在真正重要的地方。 这篇文章记录的,就是我目前用来减少 AI 代码返工的一条实践路径。 一、我以前把 AI 当成“写得更快的人”,后来发现它更像“放大器” 刚开始用 AI 写代码时,我最在意的是它能不能一次生成几百行、能不能把一个需求快速改完。后来真正经历了几轮线上问题、PR 返工和反复讨论,我才意识到:AI 放大的不只是产出速度,也会放大需求里的空白、上下文里的误导和开发者自己的错误判断。代码生成得越快,如果没有同步增加验证能力,Review 只是被动接收更多半成品。 我最近看了一些开发者分享和团队实践,大家的结论其实很接近:不要把“AI 写了多少代码”当成成功指标,而要看它是否减少了无效沟通,是否能在进入人工 Review 前被自动检查,是否让 reviewer 更快理解真正的风险。GitHub 的官方建议也很直接:先检查功能、上下文和意图,再看代码质量、依赖和安全;最终合并责任仍在开发者身上。我现在给自己的目标因此换了一个说法:不是保证 AI 一次写对,而是让错误尽可能早暴露,让每一轮修改尽可能小,让机器能判断的事情不要消耗人工判断,让必须由人判断的事情明确标出来。 二、写之前先做上下文盘点:不要让 AI “自己理解整个仓库” 我遇到过最浪费时间的一类任务,是直接对 Agent 说“先理解一下这个仓库,再实现功能”。小项目这样做问题不大,仓库一大,Agent 往往会先花很多时间猜目录结构,读到相似但已经废弃的实现,最后在错误的上下文上给出一份看起来很合理的方案。社区里有开发者把自己的流程总结成:先画仓库地图,再找相关文件,检查上下文是否足够,最后检查回答是否确实基于这些文件。我照着这个思路调整后,最大的变化不是回答更长,而是少了“改错文件”和“参考旧逻辑”的返工。 我现在会把任务拆成四步: 先定位:让 AI 只列出与任务直接相关的目录、入口、调用方、测试和配置,不要马上改代码。 再确认:让它说明每个文件为什么相关,哪些文件只是相似样例,哪些内容可能已经过期。 再补上下文:补充接口契约、数据库结构、历史 PR、业务规则和失败案例;如果这些信息没有提供,就明确标成未知。 最后锁范围:规定允许修改的文件和不允许顺手做的重构,要求它在动手前复述范围。 我会先使用这样的提示: 先不要写代码。请完成以下任务: 1. 列出本任务涉及的入口、调用链、数据结构、测试和配置; 2. 区分“已从仓库确认的事实”和“你的推测”; 3. 指出还缺少哪些上下文,以及缺失它们会影响什么判断; 4. 给出最小改动计划,列出准备修改和明确不修改的文件; 5. 等我确认计划后再实现。 这里有一个容易被忽略的细节:我不会把所有文档一股脑塞给 AI。上下文太多同样会稀释重点,我更倾向于使用“渐进披露”:先给仓库地图和任务相关文件,遇到具体问题再补充协议、ADR、历史 PR 或业务文档。AI 必须回答“我实际参考了哪些文件”,而不是笼统地说“我已经理解整个项目”。上下文的关键不是多,而是相关、最新、可核对。 如果它引用了过期文档,我会先停下来校正上下文,而不是继续修补错误答案。 ...

2026-08-26 · 2 min · 246 words · FunkyGod

AI 编程时代,我愿意用 Go 做后端

AI 编程时代,我愿意用 Go 做后端 AI 编程工具越来越会写代码,但真正把一个 AI 应用跑到线上,难点从来不只是"能不能生成一个接口"。请求超时怎么处理,模型服务失败后怎么重试,流式响应如何关闭,服务占多少内存,镜像怎样发布,出了问题能不能快速回滚,这些才是后端每天要面对的事情。 我越来越愿意把 Go 放在 AI 应用的后端位置:让 AI 负责加快实现,让 Go 负责把边界、资源和部署约束固定下来。这里说的不是把模型训练和推理强行改写成 Go,而是模型外围的 API、网关、任务和编排服务。蓝色文字表示语言和工程特性,绿色文字表示我的实践判断,红色文字表示容易被忽略的风险,黄色底色表示可以直接采用的做法。 一、Go 不会让 AI 更聪明,但会让错误更快暴露 我用 AI 写后端时,最常见的情况不是代码完全不能运行,而是它给出了一条顺利路径,却把失败路径一笔带过。比如调用大模型时,AI 很容易生成下面这种代码: func AskModel(prompt string) string { resp, _ := http.Get("http://model:8080/v1/chat") body, _ := io.ReadAll(resp.Body) return string(body) } 这段代码的问题很多:忽略了网络错误,没有关闭响应体,没有设置超时,也没有检查状态码。它可能在本地演示中返回结果,但一旦模型服务变慢,连接就可能长期占用;一旦服务返回 500,调用方拿到的可能仍然是一段错误页面。 Go 的显式语法会把这些问题推到台面上。error 必须被接收,类型转换必须写明,defer、context 和 goroutine 的生命周期也不会凭空消失。 这对 AI 生成代码形成了一种很有价值的约束:编译器先拦住低级问题,人再检查业务决策。 例如,我会要求模型先生成一个"责任完整的版本": var ErrModelUnavailable = errors.New("model service unavailable") func AskModel(ctx context.Context, client *http.Client, endpoint string, prompt string) ([]byte, error) { payload, err := json.Marshal(map[string]string{"prompt": prompt}) if err != nil { return nil, fmt.Errorf("encode model request: %w", err) } req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewReader(payload)) if err != nil { return nil, fmt.Errorf("create model request: %w", err) } req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return nil, fmt.Errorf("call model: %w", err) } defer resp.Body.Close() if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices { return nil, fmt.Errorf("model returned status %d: %w", resp.StatusCode, ErrModelUnavailable) } body, err := io.ReadAll(io.LimitReader(resp.Body, 4<<20)) if err != nil { return nil, fmt.Errorf("read model response: %w", err) } return body, nil } 这里不是说 Go 写起来没有重复代码,而是每个关键动作都落到具体的代码位置:编码、请求、响应、释放、超时、错误,全都看得见也改得动。 ...

2026-08-24 · 4 min · 666 words · FunkyGod

学习和理解 OpenAI 的 Responses:模型调用过程的原子事务

学习和理解 OpenAI的Responses:模型调用过程的原子事务? Responses 的核心价值,不是把接口名称从 Chat Completions 换成了 responses,而是把模型调用从“返回一段文本”升级成了可组合、可追踪、可继续执行的结构化结果。一次调用可以同时产出最终消息、函数调用、内置工具调用和受控的推理摘要;应用不必再把所有信息塞进一段字符串里猜测和解析,而是可以按 item 类型决定下一步动作。 这个变化真正解决的是 Agent 工程里的三个问题:模型做了什么更容易追踪,工具调用怎么接续更清楚,失败后从哪里恢复更具体。最近和同事讨论 OpenAI 的 Responses API,我发现最容易混淆的不是请求怎么发,而是“一次 Response 到底装了什么”。我现在更愿意把它理解成:一次有结构的模型调用记录。它可以成为调试、审计和多轮协作的共同载体,但它不是数据库里的 ACID 事务,也不是默认把完整思维链交给用户。“原子事务”只是一种帮助理解的比喻:工程上真正要记录的是调用 ID、item 类型、工具结果、失败状态和业务幂等关系 ┌─────────────────────────────────────────────────────────┐ │ Responses 协议心智图 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 你发起 ──→ 一次 Response(原子事务) │ │ │ │ │ ├── input (输入) │ │ ├── instructions (系统级设定) │ │ ├── tools (可选能力清单) │ │ │ ├── 内置工具 (web/file/code/MCP)│ │ │ └── 自定义函数 │ │ ├── previous_response_id (状态游标) │ │ └── stream / background (执行模式) │ │ │ │ 服务端返回 ──→ 一个 Response 对象 │ │ │ │ │ └── output[] (异构工件清单) │ │ ├── reasoning (思维证据) │ │ ├── tool_call (动作证据) │ │ │ ├── 入参 │ │ │ └── 结果 │ │ └── message (交付物) │ │ │ └─────────────────────────────────────────────────────────┘ ...

2026-08-24 · 3 min · 578 words · FunkyGod

AI 一口气生成几百行代码,我们该怎么高效且正确地处理代码审核

AI 一口气生成几百行代码,我们该怎么高效且正确地处理代码审核 一、当 AI 能在一分钟里吐出一两百行代码时,真正的难点早已不是“写不出来”,而是“接得住、查得动、改得回、负责得起”。我自己一天常常让 AI 写十几轮,单次 50–300 行很常见,一周下来累计几千行并不夸张。这里面能直接合进主干的大概只有一半,剩下要么是风格不一致、要么是越权操作、要么是没覆盖到我期望的边界,真正被我留下来再加工的常常只有三分之一。速度确实上去了,但读、改、回滚这些事没有便宜半分。我需要同时做目标设计者、规则制定者和成果验收者:先把问题、边界和验收条件讲清楚,再让 AI 在明确的范围里多试几种写法、多跑几轮检查,最后由我看差异、看风险、看回滚路径,再决定是否合并。这一顺序不能反过来——如果我自己都不知道“完成”长什么样,再快的生成也只是把模糊需求放大成更难检查的代码。带着这个结论再读这个题目,会更容易看清它真正在问什么:不是“AI 写得太快怎么办”,而是“当写的成本被工具压平以后,程序员到底该把时间花在哪几个动作上,才能既不返工,也不背锅”。 二、过去半年我最大的感受是,AI 把“写一段代码”的价格压下去了,但“看懂一段代码”的价格几乎没变。一个函数能不能写出来,今天大多数时候已经不构成瓶颈;真正占用时间的,是它处在什么上下文、用了哪些约定、隐含了哪些假设、会不会影响别的模块。一个项目里如果突然多出几百行 AI 代码,常见问题不是“明显错误”,而是“看起来很像正确答案”。我整理了几类实际反复遇到的偏差:在 Go 项目里写出 Python 风格的命名(snake_case 夹杂驼峰、把 换成 ),在 React 项目里调用一年前版本的 清理写法,在 iOS 项目里把 写成一串 嵌套,在 SQL 里写出 ORM 不能识别的方言。这些都不算 Bug,跑得起来,过得了 lint,但放进项目里就是和团队既有代码打架。错误处理走的是另一套约定、用了项目里没人熟悉的依赖、或者把一份本该抽出来的逻辑写成了复制粘贴,也都同源。这并不是 AI 不努力,而是它默认按“训练里最常见的写法”回答,而不是按“这一个项目里最合理的写法”回答。读代码一旦要一边猜意图、一边查背景、一边补差异,效率马上塌掉。所以处理 AI 批量生成代码的第一个动作,不是立刻评审,而是先把这些代码放到一个能被人快速消化的上下文里:让它先和现有约定对齐,再让它进入人的视线。我自己的小习惯是:先跑一遍项目的 formatter / import-sort / gofmt-prettier / eslint --fix,把肉眼可见的风格差异抹掉,再开始看逻辑。看起来是小事,能省下 review 时一半的争论。 三、把 AI 当成“一小时能写完一周活”的同事是不够的,更准确的定位是:它负责在明确边界内把重复部分做出来,人负责在模糊地带做判断。越模糊的需求,越不该直接交给 AI;越清晰的接口,越适合让 AI 多试几种实现。具体到我自己:在把任务交给 AI 之前,我会先填一份简短的“任务说明模板”,哪怕只是几行清单: 目标:这次改动要解决什么,用一两句话讲清楚; 不能破坏的行为:列出已有的功能、API 兼容点、对外契约; 验收条件:包括成功路径、失败路径、边界输入、需要的日志或埋点; 范围:哪些文件/模块允许改动,哪些只能引用不能改; 测试:要求覆盖的关键 case(哪怕只是几条自然语言描述); 依赖:允许引入哪些新包,是否需要更新 lockfile、是否要走安全 review。 这份清单写在 issue、PR 描述、或者本地 prompt 模板里都行。我自己最常用的是把它贴在每次开新对话的第一段,让 AI 在生成前自己复述一遍——如果 AI 的复述和我理解的不一致,我先纠正它,再让它写代码。这一步看起来比直接生成慢一点,但它避免了我最怕的那种返工:代码已经写得很长,最后才发现我根本没想清楚要的是什么。一旦让 AI 开始写,我会刻意要“两三种实现思路”,而不是一个最终答案:每种思路分别有什么取舍、依赖、风险点,分别适合什么场景。AI 在这里负责的是“扩宽选择范围”,我负责的是“决定走哪条”。判断做完之后,AI 仍然很有用:写样板、补测试、翻译接口、改一处风格、批量重命名——这些是它擅长、我也乐意外包的部分。把“想清楚”和“写出来”分成两步,比把“想”也外包出去重要得多。 ...

2026-08-23 · 2 min · 228 words · FunkyGod

AI 时代,程序员该怎么理解"富在术数,不在劳身;利在势居"

AI 时代,程序员该怎么理解“富在术数,不在劳身;利在势居” 富在术数,不在劳身;利在势居,不在力耕也。 一、先说我的结论:在 AI 时代,正确使用 AI 不是把思考和责任交给它,而是让它处理重复、检索、整理和初稿,把问题定义、边界判断、结果验证和最后负责留在自己手里。我需要同时做目标设计者和成果验收者:先想清楚要解决什么,再让 AI 多想几种办法、多试几次,最后由我判断结果是否合格。这个顺序不能反过来:如果我连问题是什么、什么结果算完成都没有想清楚,就算 AI 很快生成了一大段代码,也只是把模糊变成了更难检查的复杂。带着这个结论再读这句话,会更容易看清它的意思。这句话出自西汉桓宽整理的《盐铁论·通有》,不是《韩非子》。原文讨论燕地的涿、蓟,赵地的邯郸等名都为什么富裕。它们不一定拥有最肥沃的土地,却处在交通要冲,货物、商人和消息从那里经过,远方的资源可以在那里交换。这里的“术数”不是一个人凭空想出的小聪明,而是经营、组织和交换的方法;“势居”也不是今天常说的追风口,首先是你处在什么位置,是否连接着货物、需求和交易。这个背景很重要,因为《盐铁论》并没有单纯赞美商业。贤良文学马上反驳:商业繁盛可能带来奢侈、逐利和农业荒废;后面的争论又回到盐铁、均输、平准,讨论国家要不要介入资源和交易。也就是说,这句话真正提醒我们的不是“不要劳动”,而是:财富不会按照体力和工时一比一地分配,分工、流通和位置同样会决定劳动能产生多大结果。我以前读到这句话时,很容易把它理解成“方法比努力重要”;现在我更愿意把问题再往前推一步:一个人的劳动,怎样才能不只完成一次任务,而是进入一套更大的协作关系,留下以后还能使用的东西。 二、放到程序员身上,“劳身”不只是敲键盘,也包括那些只能随着工时增加、任务结束就归零的工作:接一个需求、写一组接口、改一个页面、处理一次线上故障、给别人解释一次项目结构。这些工作当然有价值,没有它们系统不会运行,用户的问题也不会解决;但如果我的收入和影响力永远只取决于“今天完成了几个任务”,就会遇到一个很现实的上限:一天只有这么多时间,注意力也会疲劳。我自己处理重复问题时经常掉进这个循环:某个接口出错,我查日志、改代码、补测试,问题解决;过几周同类问题再次出现,我又从头查一遍。每次都很忙,但忙完没有留下什么,下一次仍然要拿当天的时间重新换结果。AI 把这个问题放大了。生成样板代码、补充测试、解释报错、转换接口格式,这些工作正在变快,也正在变便宜。如果我只把优势建立在“比别人多写一点普通代码”上,这部分优势很容易被工具追平。AI 首先压低的是“写出一段代码”的价格,不是“让一个系统可靠运行”的价格。后者还包括判断问题值不值得做、把模糊需求说清楚、处理旧系统的限制、验证生成结果、控制权限和成本,以及出了问题之后能够定位、回滚并负责。代码越容易生成,程序员越不能只证明“我能写出来”,而要证明“我知道为什么这样写、怎样确认它没有伤害原来的系统”。 三、我现在理解的“术数”,不是几个提示词,而是把一次解决问题的经验变成下一次可以重复使用的办法。比如我让 AI 修改一个功能时,不再只说“帮我改好”,而是先写清楚目标、不能改变的行为和验收条件,再让它给出两三种实现思路,说明各自的风险。我会多用 AI 去 try:试不同的拆分方式,试几组边界输入,试着找出自己方案里的漏洞;但这些尝试只是帮我扩大选择范围,最后仍由我判断哪种方案值得做,运行测试、查看差异、检查权限和回滚路径,再决定是否验收。这个流程看起来比直接生成代码慢一点,但它减少了我最怕的那种返工:代码已经写了很多,最后才发现需求根本没有定义清楚。类似地,一个故障处理完以后,我可以只说“已经修好了”,也可以留下排查路径:先看哪类日志,哪些指标能排除某种原因,什么情况需要回滚,修复后补哪一条测试。下一次遇到同类故障,这份记录就不只是文档,还能成为人和 AI 都能照着执行的步骤。再往前一步,我会把重复的接口规范、错误处理、权限检查和测试方式整理成模板或自动检查,让团队其他人也能用。第一次做这些整理确实会增加时间,但第二次、第三次开始,我不必重新解释、重新试错、重新检查。这才是我理解的“术数”:不是让自己看起来更聪明,而是让一件事情下次更容易做好,并且不再完全依赖某个人临场发挥。AI 最适合参与的,也正是已经想清楚的流程:生成重复部分、收集失败案例、补齐检查项,而不是替我决定问题是什么。 四、“势居”对程序员的意义,是不要永远停在代码生产的末端,而要逐渐靠近问题、数据、使用者和运行结果。我以前也把“势”理解成热点:哪个模型发布了就赶紧试,哪个概念流行了就做一个 Demo。但热点往往只带来注意力,不一定带来位置。一个更实际的判断是:我是否知道用户每天反复遇到什么麻烦?是否看过真实输入和错误案例,而不是只拿几个漂亮样例测试?我写的东西是否进入持续运行的系统,而不是演示页面?上线后出了问题,我是否能看到结果并继续修改?比如临时帮别人总结一份日志,完成一次就结束;如果我长期处理同一类系统的日志,知道哪些错误最常见、哪些指标最有用、哪些修复会影响其他服务,再把这些经验做成团队每天使用的工具,我接触到的就不只是一次任务,还有问题的历史、数据的变化和用户的反馈。真正的“势”不是你站在风口上,而是一个重要问题长期存在时,别人会因为你的经验、工具和判断而经过你。但我也不想把这句话写成“只要努力就能占据有利位置”。一个人能不能接触用户、拿到数据、决定方向,还取决于组织、平台和资源。不是每个程序员都能马上拥有入口;有些人一开始就在交通要道,有些人只能按别人的订单计时。因此更诚实的问法是:我是否比半年前更接近问题源头、更了解运行结果,是否积累了一些可以带走的经验,而不只完成过一串无法复用的任务?如果一个 AI 机会只让我承担更多重复劳动,却不让我接触问题、反馈和决策,那么它可能只是把旧的劳身换了一个更时髦的名字。不能因为“势居”听起来有道理,就把所有结构性的差距都解释成个人不够努力。 五、如果把这句话落到我自己的工作安排里,我不会先问“下一个最热的 AI 工具是什么”,而会先看最近一个月的任务记录:哪些工作出现次数最多,哪些地方最容易出错,哪些问题每次都要重新解释。然后选一个结果容易检查、出错代价不高的任务,先由我写清楚目标和验收条件,再让 AI 多给几种方案、多试几组输入、多模拟几种失败情况;我不把第一次生成的结果当答案,而是把它当一个可以继续追问、修改和推翻的草稿。连续使用几次后,重点记录它在哪些地方误判,以及我自己的目标是否写得不够清楚;最后把稳定下来的步骤整理成脚本、测试、说明或团队工具,并找真正使用它的人确认是否减少了麻烦。这个顺序对我很重要,因为一个只在顺利样例里工作的 AI 流程没有多少价值,真正有用的东西往往来自失败、误判和人工接管。回到原句,我的理解不是“努力没用”,也不是“找到风口就能成功”,而是:如果劳动只完成一次任务,回报容易被时间限制;如果劳动被整理成方法、工具、系统和信任,才有机会被重复使用;如果我只站在代码生产的末端,容易被比较和替代;如果我逐渐靠近真实问题、用户反馈和系统结果,就更可能形成自己的位置。先把基本功练好,再把重复工作交给 AI;先在真实项目里待久一点,再判断自己的位置;先积累能复用的东西,再谈所谓的风口。给读者的启示:1. 多思考目标、边界和验收条件;2. 多尝试,不把 AI 的第一次答案当结论;3. 多用 AI 去 try,让它提供方案、反例和试验;4. 自己做目标设计者和成果验收者;5. 让 AI 放大判断,而不是替代判断,生成越快,越要重视测试、监控、回滚和对结果负责。

2026-08-21 · 1 min · 48 words · FunkyGod

Go + Python 混合开发:两种语言的协同,我觉得很舒服

Go + Python 混合开发:两种语言的协同,我觉得很舒服 原文:Python 与 Go 混合开发 | 让 Golang 编程更丝滑 作者:原文信息未提供 来源:用户提供原文标题,发布平台及发布日期未详 很多团队并不是在 Go 和 Python 之间二选一,而是在同一个系统里同时使用它们:Python 负责模型、数据和快速试验,Go 负责服务、任务、网络和部署。 这种组合听起来很自然,真正做起来却经常出现另一种结果:两边各自开发都很顺,连在一起就变得不顺。调用延迟、数据转换、错误处理、版本发布和线上排障,很快会把“语言互补”变成“系统加倍复杂”。 原文从开发体验出发讨论 Python 与 Go 的混合使用。本文在这个基础上往前走一步:混合开发的核心不是把两种语言硬塞进一个进程,而是为变化速度不同的模块设计清晰、可观察、可演进的边界。 蓝色文字表示核心判断,绿色文字表示个人开发实践,红色文字表示风险提示,黄色底色表示可以直接执行的建议。 一、先纠正一个误区:混合开发不是“Python 慢、Go 快” 用“Python 负责灵活,Go 负责性能”概括两种语言,虽然容易理解,但不够准确。 Python 的价值不只在于写得快。它连接着成熟的数据处理、科学计算、机器学习和实验工具链。研究人员或业务工程师可以很快把数据读进来,换一个模型,调整参数,观察结果,再决定下一步怎么做。这个阶段最宝贵的是试错速度和生态覆盖面。 Go 的价值也不只是运行速度。它的静态类型、编译器、并发模型、标准库和独立二进制发布方式,更适合承载长期运行的服务和工具。一个网关、任务调度器、文件处理器或消息消费者,往往要面对超时、取消、限流、重试、优雅退出和故障恢复。这些问题的难点不在于写出第一版,而在于运行数月后仍然清楚、稳定、可维护。 所以,合理的分工不是“把慢的代码改成 Go”,而是看模块的主要矛盾是什么: 变化快、需要不断试验、依赖模型和数据生态的部分,优先考虑 Python; 需要长期运行、并发处理、跨平台发布和严格运维的部分,优先考虑 Go; 两者都能完成、但没有明确收益的部分,不要为了“混合”而混合。 语言边界应该服从业务边界。一个稳定的 Python 服务,通常比一个为了追求统一而重写的 Go 服务更有价值;一个需要高并发和强约束的 Go 组件,也不应该因为团队已经熟悉 Python 就继续堆补丁。 二、最常见的协同架构:Python 做变化,Go 做秩序 在 AI、数据和平台型系统中,可以把职责粗略分成四层。 1. Python:模型和数据层 Python 适合放置以下内容: 模型加载、推理和评测; 特征处理、数据清洗和离线任务; 提示词编排、实验脚本和策略验证; 需要频繁调整的业务规则; 对第三方 AI、科学计算或数据工具的适配。 这一层的代码变化频率通常较高。它不一定要承担所有外部流量,也不一定要直接管理复杂的重试和权限体系。 ...

2026-08-20 · 4 min · 656 words · FunkyGod

Go 是 AI 辅助软件工程的理想语言:原文解读与深入思考

Go 是 AI 辅助软件工程的理想语言:原文解读与深入思考 原文:Why Go is an Ideal Language for AI-Assisted Software Engineering 作者:Cameron Balahan(Go 产品组经理)、Richard Seroter(Google Cloud 首席布道师) 来源:Google Developers Blog 发布日期:2026 年 8 月 11 日 本文分两部分:第一部分忠实解读原文,还原文章的论证结构与核心观点;第二部分跳出原文,从批判性视角深入探讨这篇文章没有说透、值得追问的地方。 第一部分:原文解读 1. 文章的出发点:软件工程正在发生范式转移 文章开篇没有直接讲 Go,而是先描述了一个正在发生的行业变化: 过去,我们亲手写大部分代码;现在,我们让 AI 编程助手和智能体替我们生成大量代码。但 AI 需要监督,所以依然是我们人类来阅读生成出来的代码、清理它、并验证它是否真的做了我们想让它做的事。 这是全文的地基。作者想表达的核心是:代码的"生产"变便宜了,但代码的"治理"并没有变便宜。 紧接着,作者补充了一个容易被忽略的事实:AI 只能看到它被喂进去的那点上下文,看不到整个系统的边界。因此,系统架构、服务边界、生产环境的安全与可靠性,仍然必须由人来定义和负责。 这一段的潜台词是:AI 改变了"写代码"这件事,但没有改变、甚至放大了"软件工程"这件事的难度。 2. 第一个核心判断:瓶颈从"写"转向了"审" 作者回顾了历史:过去,人们衡量一门编程语言的生产力,主要看它"好不好写"。 但当 AI 能在几秒钟内生成几百行语法正确的代码时,人类写代码的速度就不再重要了。真正重要的事情变成了三件: Reviewing——评审; Verifying——验证; Maintaining——维护。 文章用了一个形象的比喻:AI 越来越像你的队友(teammate),一个有点我行我素、但仍然算队友的存在。既然如此,最重要的就不再是"我写得有多快",而是"我们作为一个团队如何协作"。 这是全文第一个关键转向:衡量语言的坐标系,从"个人写作体验"切换到了"团队协作体验"。 3. 第二个核心判断:Go 是为"软件工程"而生的 作者指出,二十多年前 Rob Pike、Robert Griesemer 和 Ken Thompson 在 Google 创建 Go 时,别的语言都在快速堆砌特性、扩展表达方式,而 Go 选择的却是一个更大的目标: ...

2026-08-20 · 3 min · 559 words · FunkyGod

Go 语言在 AI 辅助编程时代被谷歌官方力挺:动态语言与 Go 并非对立,而是互补关系

Go 语言在 AI 辅助编程时代被谷歌官方力挺:动态语言与 Go 并非对立,而是互补关系 原文:谷歌官方力挺:为什么 Go 语言是 AI 辅助编程时代的“标准答案”? 作者:场长 来源:21CTO 公众号,发布于 2026 年 7 月 16 日 过去,程序员最关心的问题是:哪门语言写起来更快? 进入 AI 辅助编程时代后,这个问题正在变成:哪门语言更容易让 AI 写对,也更容易让人类看懂、验证、部署和维护? 这不是文字游戏,而是软件生产方式发生变化后的真实转向。AI 可以在几秒钟内生成数百行代码,却无法替人类承担全部架构责任。代码越容易生成,审查、测试、安全和运维的重要性就越高。 谷歌官方力挺 Go,核心并不是说 Python、JavaScript 或 TypeScript 已经过时,而是指出:Go 从诞生之初就偏向大型、长期运行的软件系统。在智能体持续生成代码的今天,这些原本服务于人类团队的设计原则,也恰好成为 AI 协作所需要的“确定性护栏”。 更准确的结论应该是:动态语言负责快速探索和连接生态,Go 负责把经过验证的能力变成稳定运行的服务、工具和基础设施。 一、AI 编程真正改变的,是软件开发循环 很多人提到 AI 编程,首先想到的是代码补全:输入函数名,AI 自动写出函数体;写一段注释,AI 生成一段实现。 这只是最早期、也最简单的用法。 真正的 AI 辅助编程,通常是一个持续循环: 实现 → 构建 → 测试 → 分析失败 → 修改 → 再次构建。 如果是能够自主操作终端和代码仓库的智能体,它还会继续执行:读取日志、搜索依赖、修改多个文件、运行集成测试、启动服务、调用接口,然后根据结果再次修复。 对人类开发者来说,几分钟的编译等待可能只是一次短暂的停顿。对一个需要运行几十轮的智能体来说,每一次等待都会累积成时间、算力和模型调用成本。 这会放大许多过去被忽略的工程摩擦: 构建速度慢:每次修改都要等待更久,智能体的有效迭代次数下降; 依赖关系复杂:环境安装失败后,智能体可能把大量上下文消耗在解决版本冲突上; 错误反馈太晚:问题到运行时才暴露,智能体可能已经在错误基础上写了更多代码; 代码风格不统一:人类和 AI 都要花时间理解不同写法,评审速度自然下降; 部署链路过长:代码虽然生成了,但服务无法稳定启动,任务仍然不能算完成; 生态变化太快:模型根据旧文档生成的代码,可能在今天已经不适用。 过去,这些问题可能每周出现几次。现在,智能体可能在一天内把同一个循环执行数百次。问题没有变,但问题出现的频率变了,成本结构也随之变化。 ...

2026-08-20 · 2 min · 417 words · FunkyGod