在编程语言领域,很少有哪个话题像“异步I/O该怎么设计”这样反复撕裂社区:Go用goroutine一力降十会,Rust用async/await染了色,Java被回调地狱折磨后才有虚拟线程。而Zig——这门以“没有隐藏控制流”为信条的系统级语言——在2024年干脆删掉了自己第一版异步实现,然后在一年多后端出了全新的方案。本文深度解读的这条视频,就是Zig创始人Andrew Kelley在Zigtoberfest 2025大会上对这套新异步I/O的首次系统性公开演示。它于2025年10月末发布,此后近一年里随着Zig 0.16版本的临近与社区的持续争论不断回热,HN讨论串到2026年7月仍有新评论涌入。这条视频真正值钱的地方在于:它不是API教学,而是一堂关于取消(cancellation)、结构化并发与API设计哲学的公开课——这些概念可以迁移到你正在用的任何一门语言。
| 项目 | 内容 |
|---|---|
| 视频标题 | Zig's New Async I/O - Andrew & Zig Core Team |
| 中文译名 | Zig的新异步I/O —— Andrew与Zig核心团队 |
| 频道 | Zigtoberfest(Zig社区年度活动官方频道) |
| 演讲者 | Andrew Kelley(Zig软件基金会主席、Zig主开发者) |
| 发布时间 | 2025年10月29日 |
| 时长 | 57分54秒 |
| 播放量 | 29,542(据YouTube页面,2026-08-30抓取) |
| 点赞数 | 684(据YouTube页面) |
| 分类 | Science & Technology |
| 社区热度 | HN讨论329分、172条评论;文字版博客同期发布 |
这场演讲的结构非常克制:Andrew准备了一个渐次推进的例子序列,从纯同步代码出发,每一步只引入一个新概念,全程允许现场打断提问。按叙事顺序,这套论证可以拆成五个层次。
前两个例子还没碰async。Andrew先展示在Zig 0.16的标准I/O里,你首先要初始化一个“I/O实现”(IO implementation)——他演示的是基于线程的实现,并特别强调“这不是kqueue,不是io_uring,也不是事件循环”。这个设计呼应了Zig最著名的模式:分配器(allocator)永远是显式传入的参数。I/O接口同样是一个“胖指针”(fat pointer),与分配器的接口方式完全同构。演讲后段的问答里,核心团队成员展示了Zig编译器真实代码库中的写法:allocator和io就作为结构体字段躺在上下文对象里,随调用链传递。
这个开场确立了整场演讲的基调:异步不是语言魔法,而是一个你可以选择、替换、甚至自己实现的库设施。同一个业务代码,可以跑在线程实现上,也可以换成基于io_uring的高性能实现,还可以换成用于测试的“单线程无并发”实现。
第三个例子给出全片最核心的定义。Andrew说,async/await在Zig里的含义只有一句话:解耦函数的调用和函数的返回(decouple the calling of a function from the returning of a function)。普通的函数调用是“调用→等待→返回”三合一;async把“发起调用”和“等待结果”拆成两个独立的时间点,中间你可以做别的事。类型系统上体现为Io.Future(T),await操作是幂等的——重复await同一个future,行为完全一致。
紧随其后的例子立刻展示了这么做的意义:两个各“工作”一秒的任务,如果表达为异步,总共只等一秒。关键洞见是,你的代码只是在声明“这两个操作彼此独立、不必互相等待”,至于这份独立性能不能兑现成实际的速度提升,取决于你选的I/O实现有没有并发能力。这把“意图表达”与“资源调度”干净地分开了。
这是整场演讲最有含金量的部分。第四个例子制造了一个真实场景:两个并发任务中第一个返回了error.OutOfMemory,代码用try处理——结果泄漏检测器立刻报警:第二个任务成了孤儿,被泄漏了。Andrew坦率地说:“这是个bug,虽然我们很想那样写代码。”
修复方案引出了cancel原语,其语义精炼到极致:cancel与await完全相同,只是额外请求取消,且同样幂等。于是诞生了Zig风味的配对模式——就像defer free配对alloc一样,async之后紧跟defer cancel。这不仅修掉了泄漏,还带来一个意外红利:当try因第一个任务的错误提前返回时,defer触发cancel,仍在等待的第二个任务瞬间被取消,整个程序近乎瞬时结束。
更漂亮的是取消的传播机制。因为Zig里取消被建模为一个错误值error.Cancelled,它会顺着普通的错误处理链路自动向上传播——你为内存、文件句柄写的那些错误清理代码,在取消发生时会被原样走过一遍。Andrew的原话是:“你通常完全免费地获得取消传播”,只有CPU密集型代码才需要手动插入检查取消的点位。
讲到中段,Andrew专门花了一个例子区分两个被混用多年的概念。生产者-消费者通过一个无缓冲队列传递令牌,用async派生两端,程序跑起来一切正常。然后他做了个手术:把I/O实现的CPU数限制为1。同一份代码,死锁——消费者阻塞在队列上等数据,生产者被调度了却没线程可跑。
结论被浓缩成一句可打印出来贴墙上的话:你请求的是异步(asynchrony),需要的却是并发(concurrency)。修复方式是把io.async换成io.concurrent——后者明确声明“这两个任务必须真的同时执行”,当实现做不到时(比如单线程模式),它会返回一个可处理的错误ConcurrencyUnavailable,而不是死锁。演讲现场甚至发生了一个小插曲:Andrew在演示超额订阅(oversubscription)边界情况时,当场发现了线程实现里的一个真实bug,并对着满屋子人现场debug——“我想我刚刚意识到我犯的bug在哪了”。这个未被剪掉的翻车瞬间,恰恰是这场演讲作为“设计进行时”文档的真实价值。
收尾部分展示了两个组合原语。group被Andrew称为“任务的arena(竞技场分配器)”:你可以往group里不断async派生任务,然后对整个group统一等待;它内部只需一个计数器而非逐个追踪资源。一位核心团队成员补充了关键细节:group里的任务完成时资源即刻回收,因此可以用group承载长期存活的东西——比如一个HTTP服务器为每个连接派生一个任务,全部丢进一个group,不会随时间泄漏。
select则解决“多个future赛跑,谁先完成用谁”的问题:编译期版本接受一个future的结构体,靠编译期反射生成结果联合体供你switch;运行期版本直接接受联合体,可在循环里动态添加。而这两者底下,都可以用group加队列这些更基础的原语自己搭出来——原语虽少,组合 expressive。
结构化并发(Structured Concurrency)。group原语与“任务生命周期不得逃逸出作用域”的思想,直接对应Nathaniel J. Smith 2018年的著名长文《Notes on structured concurrency, or: go statement considered harmful》。那篇文章批评Go的go语句让并发任务像脱缰野马,提出trio语言库的“nursery(育儿室)”概念:子任务必须被某个作用域收养,作用域退出前所有子任务必须完成或被取消。此后Kotlin的coroutineScope、Swift的TaskGroup相继落地同一思想。Zig的group加defer cancel组合,是这个谱系里第一个“无垃圾回收、显式内存管理”语言的原生实现。
Zig自身的“无色异步”兴衰。据Zig官方公开资料,Zig曾在0.10/0.11时代提供过“函数颜色无关”的async/await——编译器为普通函数自动生成挂起版本,号称消灭“函数染色问题”。但这个方案在2024年的0.12开发周期被整体移除,官方给出的理由包括实现复杂度与实际收益不匹配。本片演示的新方案是一次彻底的路线修正:不再追求语言级魔法,而是回到“显式接口、显式实现”的Zig传统。理解这个背景,才能听懂现场问答里那句略带自嘲的“Andrew不喜欢匿名函数,所以这个决定不会改”。
操作系统异步I/O的工程脉络。Andrew特意点名“这个线程实现不是kqueue、不是io_uring”——这两个名字背后是三十年异步I/O演化史:BSD的kqueue(2000年)、Linux的epoll(2003年)确立了事件循环范式, Jens Axboe主导的io_uring(2019年进入Linux 5.1)则用共享环形缓冲区把系统调用开销压到接近零。Zig的新I/O接口把这些底层机制全部收编为“可插拔实现”,业务代码面对的是同一个接口。这种“接口与实现分离”的做法,与C++的executor提案、Java的虚拟线程之争,其实是同一场旷日持久的标准之争的不同答卷。
取消语义的三种流派。视频里“取消即错误”的设计,可以放进一个更大的坐标系:.NET用CancellationToken显式传递取消令牌;Python asyncio把CancelledError做成异常,风险是容易被宽泛的except捕获吞掉;Go长期没有正式取消机制,靠context手动检查。Zig的做法本质上是第四条路——利用语言已有的错误联合体通道,让取消搭乘错误传播的便车,且因为Zig的try不能吞错,取消无法被静默忽略。这不是Andrew的发明,但把它与defer/资源对称原则咬合得这么紧,是少见的完成度。
证据充分的部分。视频对async/await语义、cancel幂等性、异步与并发之别的讲解,逻辑严密且有可运行的例子支撑,现场观众步步追问,答问质量很高。这些语义层面的主张是自洽的、可验证的,也是整场演讲最可靠的部分。
需要打折扣的部分。第一,这是"design in public"(公开设计)的早期快照——核心团队成员在结尾明确警告:“这些细节几乎没有一个是定稿的……如果你现在就用,等于主动选择短期内的不稳定。”任何把片中API当作最终形态的解读都会过时。第二,性能主张在片中是缺席的:演示用的线程实现只是语义参考实现,真正基于io_uring等机制的高性能实现的效果,本片没有给出任何基准数据。第三,演讲现场的翻车(超额订阅bug)虽然真实可爱,但也侧面印证了实现的成熟度尚早。第四,播放量近三万,在编程语言设计这个垂类已属可观(对比:多数技术大会演讲播放量在数千级),HN 329分的热度集中于硬核开发者圈层——它是一条“影响力大而受众窄”的视频,如果你期待的是通俗易懂的入门内容,这条视频会很难啃。
最具争议的设计决策是把异步与并发的选择权完全交给程序员。好处显而“显式”:同一份代码可以在单线程确定性模式下复现并发bug,这对测试是无价之宝。代价是每个调用点都要做一个Go语言替你做掉的决定,而ConcurrencyUnavailable成为一个新的、必须在类型系统里处理的失败模式。社区对此的真实分歧在HN讨论中相当明显:一派认为这是Zig哲学的胜利,另一派认为这是把本该编译器解决的问题推给了用户。视频本身没有、也不可能给出裁决。
启示1:用“结构化并发”审计你现有的并发代码。不管你写的是Go、Python还是Java,都可以问一个Zig逼你回答的问题:每个并发任务的“完成或取消”路径在哪里?那些fire-and-forget的goroutine、没join的线程、没有超时的后台任务,就是未来某个凌晨三点的生产事故。给每个异步调用配对一条收尾路径——Zig的defer cancel只是这个通用原则的一种语法呈现。
启示2:把“可等待”与“需并行”分开表达。设计API时,先声明操作之间的独立关系(异步),再考虑是否真的需要物理并行(并发)。这个区分能直接改善你的测试策略:能用单线程+确定性调度复现的bug,就不要在多线程的混沌里大海捞针。Zig计划中的“种子化、可确定复现的测试I/O实现”,值得你在自己的技术栈里寻找等价物(比如Python的trio测试调度器)。
启示3:学会看“设计进行时”。这条视频最独特的学习价值,是让你完整目睹一个语言特性从草案到落地的真实过程——包括现场抓bug、包括“还没定稿”的坦白、包括“带着用例来,别光带观点来”(bring use cases, not takes)的社区参与准则。无论你关注的是哪门语言,跟踪一两个这样的公开设计过程(Zig的Zulip、Rust的RFC、Python的PEP讨论),对提升你的API设计品味,比读十篇二手教程更有用。
flowchart TD
A[同步代码基线<br/>普通函数调用] --> B[显式初始化 I/O 实现<br/>类比 allocator 胖指针]
B --> C[async/await<br/>解耦函数的调用与返回]
C --> D{业务代码只表达<br/>操作间的独立性}
D --> E[错误处理暴露问题<br/>未收尾的任务 = 泄漏]
E --> F[cancel 原语<br/>= await + 请求取消,幂等]
F --> G[defer cancel 模式<br/>取消建模为 error.Cancelled<br/>沿错误链免费传播]
G --> H[反例演示:异步≠并发<br/>单线程下 producer/consumer 死锁]
H --> I[io.concurrent 显式声明并发<br/>做不到时返回可处理错误]
I --> J[组合原语<br/>group = 任务arena / select = future赛跑]
J --> K[设计哲学闭环<br/>无隐藏控制流·显式资源管理<br/>单线程确定性可测试]
本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
