Go 语言架构|Google ADK Go 深入拆解:把 Agent 写进 Go 的工程流水线

Go 语言架构|Google ADK Go 深入拆解:把 Agent 写进 Go 的工程流水线 原文:Agent Development Kit (ADK) for Go 作者:Google ADK Go 团队(Google 官方开源项目维护者) 来源:GitHub,发布于 2025 年 11 月 06 日 我最近重新看了一遍 Google 的 ADK Go。它吸引我的地方,并不是“Go 也有一个 AI 框架”,而是它试图回答一个更实际的问题:一个会调用模型、工具和其他 Agent 的系统,能不能像普通 Go 服务一样被编译、被测试、被部署和被审查? 这篇文章不打算把官方 API 逐个翻译一遍。我会沿着自己的理解,把 Agent、工具、工作流、协议、状态和上下文串起来,也会特别标出 v1 与 v2 的边界。文中的蓝色表示工具或事实,绿色表示我的实践判断,红色表示容易踩的坑,黄色底色表示可以直接拿去用的做法。 先看 ADK Go 为什么值得单独关注。 我认为,ADK Go 的重点不是证明“Go 比 Python 快”,而是让 Agent 代码进入成熟的软件工程流程。Go 项目已有的编译器、静态检查、单元测试、依赖管理、CI 和容器化能力,都可以继续使用。 ...

2026-09-03 · 3 min · 438 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

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

Go 项目结构之争:DDD 还是简洁分层?

Go 项目结构之争:DDD 还是简洁分层? Go 项目一开始通常很简单:几个接口、几张表、几个服务函数,按 handler、service、repository 分开就能跑起来。项目变大之后,团队又开始讨论 DDD、领域模型、聚合、应用层和基础设施层。 于是问题变成了:Go 项目到底应该采用 DDD,还是坚持简洁分层? 我的答案是:不要先选择目录结构,要先识别业务复杂度和变化边界。 简洁分层不是低级方案,DDD 也不是高级方案。它们只是解决不同问题的工具。 可以把项目想成一家餐馆。简洁分层像一家小店:前台接单,后厨做菜,仓库取料,路线短,出了问题也容易找到人。DDD 更像一家菜品、库存、会员和结算规则都很复杂的连锁餐厅:重点不是把岗位拆得越多越好,而是让“什么菜能做、什么时候能退单、库存怎么扣”这些规则有明确的负责人。 小店一开始就照搬连锁餐厅的总部制度,会被流程拖慢;连锁餐厅却不能永远把所有事情都交给一个大厨。Go 项目的结构选择,也是同一个道理。 一、争论表面是目录,本质是边界 很多团队讨论架构时,第一步就是贴目录树: internal/ ├── handler/ ├── service/ ├── repository/ └── model/ 或者: internal/ ├── domain/ ├── application/ ├── interfaces/ └── infrastructure/ 但目录本身不会自动带来好的架构。真正重要的是几个问题: 哪些代码属于同一个业务能力? 哪些规则必须始终成立? 哪些变化应该被隔离? 数据库、消息队列等技术细节,是否侵入了业务决策? 一个需求发生变化时,需要修改多少个包? 如果这些问题没有答案,换一套目录只是换了一种命名方式。 架构的价值不在于让目录看起来专业,而在于让变化停留在应该停留的地方。 先用一张图看两种结构的关注点:简洁分层按“技术职责”排队,DDD 更关心“业务规则”应该被谁拥有。 flowchart LR subgraph simple["简洁分层:按技术分组"] S1["请求"] --> S2["handler"] --> S3["service"] --> S4["repository"] --> S5[("数据库")] S3 -. "规则容易集中" .-> S6["变胖的 service"] end subgraph ddd["DDD:按业务边界组织"] D1["请求"] --> D2["应用用例"] --> D3["领域规则"] D2 --> D4["仓储接口"] D4 -. "具体实现" .-> D5["基础设施"] D5 --> D6[("数据库")] end 图中没有“谁更高级”的答案。左边像小餐馆的传菜路线,胜在短;右边像连锁餐厅的岗位边界,胜在业务规则变复杂时,能把变化关在领域边界里。 ...

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