AI 可以快速生成代码,团队仍然要为这些代码的行为负责。生成速度提高后,阅读变更、验证行为和长期维护的成本,更值得纳入语言选型的判断。
Cameron Balahan 与 Richard Seroter 在 Google Developers Blog 的文章中提出,Go 面向团队协作的设计,也适合有 AI 参与的软件工程。这个判断可以从具体分工理解:Agent 负责提出实现、运行工具和根据反馈修正;开发者负责系统架构、服务边界,以及实现是否满足业务和生产要求。
1. 语言选型要考虑代码交接之后的事
Go 的设计始于 2007 年,最初的设计者是 Rob Pike、Robert Griesemer 和 Ken Thompson。他们面对的是 Google 内部大规模软件开发的问题,包括构建、依赖与团队协作,而不只是如何更简短地表达程序。
写出一个能运行的程序,只解决了软件工程的一部分。系统还要在需求变化、人员流动和依赖升级后继续工作。加入 AI 之后,代码可以由更多会话和工具生成,理解与维护这些变更的责任仍在团队。
因此,评估 Go 时,可以同时看语言和平台:gofmt 统一格式,测试工具提供反馈,modules 管理依赖,兼容性承诺降低升级成本。这些约定为人和 Agent 提供共同的工作方式。
2. 让 Agent 根据工具结果修正代码
Agent 读完自己的输出后说「应该没问题」,并没有提供新的验证证据。编译器、测试和扫描工具能够提供独立于这次生成过程的反馈,供 Agent 定位问题并再次修改。
Go 的静态类型检查可以提前拦住一部分错误,例如调用不存在的方法、传入不兼容的参数类型。开发者不必等到某条业务路径实际运行,才发现这些类型问题。
不过,类型检查有明确边界。Go 中未显式初始化的变量会获得对应类型的零值,var count int 是合法声明;编译通过也无法证明业务规则正确。金额计算错误、权限检查遗漏,或者某个合法的零值不适合业务,都需要其他验证。
内置测试与 Fuzzing 可以继续补充反馈。Fuzzing 会探索变化的输入,帮助发现边界问题;找到失败输入后,可以把它保留下来,作为修复后的回归用例。测试覆盖什么行为、断言什么结果,仍需要开发者判断。
其中,govulncheck 是 Go 官方提供、需要单独安装的工具;它并不随 go 命令自动安装。统一工具的价值,是让每轮变更获得可重复的反馈,而不是让某次检查代替全部审查。
3. 格式一致,把审查注意力留给行为
gofmt 减少了代码格式的自由度。团队成员和 Agent 不必分别决定缩进、空格和排版,代码交接时也少了一类风格争论。Go 对语言复杂度的克制,与这种统一格式一起,构成了作者看重的可读性基础。
审查者由此可以把更多注意力放在「调用了什么」「错误如何传播」「资源何时释放」等问题上。不过,格式统一不会自动消除复杂控制流、错误抽象或不安全的 API 使用。可读性帮助人发现问题,不能替代问题本身的验证。
这也说明,评价 AI 辅助开发的效果时,仅统计生成行数并不充分。一次变更需要花多少时间读懂、如何证明它符合要求,同样属于交付成本。
4. 依赖校验与漏洞扫描分别解决什么
AI 推荐的第三方包,也需要检查维护状态和实际用途。Go 的 standard library 已覆盖 HTTP、JSON、加密等基础能力,部分需求可以直接使用它们,从而减少引入第三方依赖的机会。标准库本身仍可能存在漏洞,升级与安全检查不能省略。
确实需要外部模块时,module mirror 与 checksum database 为获取和校验模块提供基础设施。校验可以帮助发现下载内容与预期记录不一致,但不能证明包的业务逻辑安全,也不能保证依赖永远可用。私有模块和 GOPRIVATE、GONOSUMDB 等配置,还会改变模块获取与校验的行为。
govulncheck 则关注已知漏洞,并结合调用关系分析代码是否触及受影响的函数。相比只看到「依赖包含某个漏洞」,调用路径能帮助开发者判断修复优先级。工具也可能给出不可达漏洞的信息性提示;没有告警,不等于不存在未知漏洞或扫描范围外的问题。
这里至少有三种不同证据:checksum 说明内容一致性,漏洞数据库说明已知风险,测试说明已验证行为。它们可以相互补充,各自都没有覆盖全部安全问题。
5. 维护成本会随着代码产量一起增长
AI 能快速提出修改,也可能让代码库更快积累不同的实现方式和技术债。Go 对长期维护的帮助,主要来自兼容性、交付方式和标准化更新工具。
Go 1 的兼容性承诺以源码为基础,目标是让符合规范的既有程序继续编译和运行。这能降低升级工具链的迁移负担,但承诺保留了安全修复、未指定行为和实现 bug 修复等例外,也不保证预编译包在版本之间保持 binary compatibility。因此,不能把它理解为「任何 Go 程序永远不会因升级出问题」。
交付方面,许多纯 Go 程序可以编译成便于分发的单个可执行文件,cross compilation 也能简化不同目标平台的构建。涉及 cgo、C 库或特定系统能力时,则仍需考虑目标工具链和系统依赖。「所有 Go 程序都完全静态、没有系统依赖」并不准确。
代码更新方面,官方 language server gopls 和 go fix 提供标准化工具。Go 1.26 重写后的 go fix 包含 modernizers,可以按确定的规则把旧写法更新为较新的惯用法。Agent 可以调用这些工具减少手工重写,但变更仍应经过 diff 审阅和测试,尤其要区分工具支持的机械更新与需要业务判断的重构。
6. 把验证延伸到生产运行
Go 的 profiling、execution tracing 和 profile-guided optimization(PGO)把维护工作延伸到了运行阶段。PGO 使用有代表性的 CPU profile 指导后续编译,使优化决策能够参考实际工作负载。它的收益依赖 profile 与生产行为是否匹配,也不能证明应用的业务正确性或安全性。
准备尝试时,可以从 Go 安装说明开始,在 VS Code 类 IDE 中安装官方 Go 扩展,并明确要求 Agent 使用项目约定的工具链验证一个小应用。先观察生成、检查、修正与审查的实际成本,再判断这套工作方式是否适合团队。
Go 为 AI 辅助开发提供了较一致的工具和代码约定。团队仍要决定需求是否实现、服务边界是否合理,以及现有证据是否足以支持一次上线。
参考资料
Go FAQ:语言设计背景与历史。
The Go Programming Language Specification:类型、变量与零值规则。
Go Fuzzing:输入探索与失败用例回归。
Go Modules Reference:模块获取、校验与私有模块配置。
Find and fix vulnerable dependencies with govulncheck:安装、调用路径分析与输出示例。
Go 1 and the Future of Go Programs:源码兼容目标及例外。
cgo documentation:C 工具链、依赖与交叉编译限制。
Using go fix to modernize Go code:Go 1.26 的 modernizers。
Profile-guided optimization:profile 采集、构建方式与适用条件。