一门今年 8 月底才公开的新编程语言,在自己仓库的 16 项基准测试里跑赢了手写 C++ 和最优 safe Rust,同时内存占用更低。更反常的是它的身份:没有堆分配器、没有垃圾回收、没有生命周期标注,编译器约 3 万行 C++ 代码,官方 README 自述「几乎全部由 Claude Fable 编写」。这就是 Wouter van Oortmerssen(游戏语言 Lobster 的作者)设计的 Goose,2026 年 8 月 30 日建仓,Apache-2.0 协议,编译产物是单个 C 文件。

起点是一个被推翻的常识
系统级语言的安全与性能之争,过去十年的主流答案是 Rust:用所有权、借用检查和生命周期标注,在编译期挡住内存错误。代价是学习曲线和标注负担,标准库代码里 'a 满天飞。
Goose 给出了第三种答案:把堆整个删掉。程序只有原生调用栈、静态数据和 N 个数据栈(N 由编译器静态算出)。每个数据栈是一大块预留地址空间加一个 bump pointer,任何时刻每个栈上至多有一个可增长值且永远在栈顶。增长就是指针前移,没有容量检查、没有搬移;作用域结束,栈顶指针写回起点,一次 store 释放整棵结构,不管它嵌套多深、有几个百万节点。
没有 malloc,就没有释放错误;没有搬移,指向增长中数组的引用永远有效;没有堆,就没有分配器元数据和碎片。安全性由编译器静态证明:每个引用都有静态根(约束其生命周期的变量),编译器推断所有引用的根并拒绝可能比宿主活得久的引用,全程零标注、零 unsafe。
数据布局:一条记录 29 字节,零分配
嵌套数据内联是 Goose 布局哲学的核心。一条订单,C++ 的 std::string + std::vector<Item> 是 160 字节 1 次分配,Rust 的 String + Vec<Item> 是 153 字节 4 次分配,Goose 是 29 字节 0 分配:
struct Item { sku: u8[varint], qty: varint, cents: varint }
struct Order { id: varint, customer: u8[varint], items: Item[varint] }
book.push(Order { id: 1001, customer: "alice",
items: [Item { sku: "SKU-441", qty: 2, cents: 1999 },
Item { sku: "SKU-7", qty: 1, cents: 500 }] });
// 29 字节:d2 0f 05 "alice" 02 "SKU-441" 04 9e 1f ...字符串、变长数组、变长字段的结构体、装着这些结构体的数组,全部是一段连续字节,内部没有任何指针。数字用 LEB128 varint 加 zigzag 编码,1001 存成两个字节。整本订单簿就是一个数组,扫描时直接流过 CPU 缓存。
数组是一个按「大小怎么变」分类的家族:T[k] 编译期定长;T[] 构造时定长后冻结;T[>..] 只增长(主力,引用永远有效);T[>..<] 增长兼收缩(栈、队列、堆);T[:] 是不拷贝的视图。字符串就是 u8 数组的各种形态:u8[>..] 是构建器,u8[..16] 是结构体内的小字符串。
比 Rust 枚举小四倍的变体模式
代数数据类型是 Goose 唯一的动态多态(没有继承、没有 vtable),每种枚举可以按两种模式存放。固定模式(Shape)是标签加最大变体的空间,可索引可改写;可变模式(Shape..)让每个值只占自己变体的实际大小。圆 9 字节、矩形 17 字节、点 1 字节,而不是每个都占 17 字节。官方基准里 1600 万条变体记录的日志:Goose 可变枚举 149 MB,Rust enum+String 593 MB,C++ variant+string 1103 MB,且 Goose 快 2.02 倍。
比指针窄的链接同样激进。相对引用把链接存成 1、2 或 4 字节的偏移:二叉树节点 { key: i32, left: Node&<u32>?, right: Node&<u32>? } 一共 12 字节,C++ unique_ptr 版本是 24 字节外加每节点一次堆分配。因为结构里没有任何绝对地址,to_bytes() 直接把整棵树写成字节流,from_bytes() 读回时校验每个标签、长度和链接,损坏或恶意的文件返回 false 而非野引用。数据结构本身就是文件格式,序列化器和 schema 都省了。
报告里的败绩
官方基准摘要(bench/summary.md,2026 年 10 月 16 日 Ryzen 9 9950X3D 运行)给出的几何平均:比惯用 C++ 快 3.51/3.54 倍(MSVC/clang),比专家优化 C++ 快 1.24/1.26 倍,比最优 safe Rust 快 1.13/1.19 倍;峰值内存分别省 1.95、1.32、1.25 倍。这些是全进程墙钟时间,含输入生成、构造和清理。
摘要同时列出输掉的项:calc(表达式解析求值)481/491 毫秒,慢于 Rust arena 的 436 毫秒;lru 在 MSVC 下 2760 毫秒对 Rust 2249(clang 下反而赢);scene 在 MSVC 下 460 对 379。对 records 类工作负载的优势(2.02-2.26 倍快、3.98 倍省内存)和 strlist 的内联字符串优势(266 毫秒对 Rust Vec<String> 的 778)则被如实归因于布局差异。摘要末尾提醒:这是单机全进程测量,不锁核心,跨日期的计时变化不能全部归因于编译器改进。
没有标注的安全,代价写在明处
引用安全之外的设计决定同样成体系。整数运算按源码宽度执行,u8+u8 是 8 位加法,有符号溢出在 debug 构建中止、release 回绕,从不未定义;u32 和 i32 混用是编译错误。错误处理不用 Result 也不用异常:return err from load 直接从任意深度调用栈中返回,静态检查每个调用点,没有 unwinder。线程完全不共享内存:每个 thread_fn 编译成独立程序带独立内存,值经类型化队列以 memcpy 穿越,数据竞争、锁、原子操作在语言里不存在。函数值是编译期实体,xs.filter() { it > 0 } 编译成它看起来的那个循环,没有闭包对象和函数指针。
代价部分 README 直接列成清单:递归函数不能跨递归调用持有可增长数据(要传 pool 进去);变长元素数组只能遍历不能索引;没有逃逸闭包、没有函数指针、ADT 标签之外没有动态派发;只支持全程序编译;还回 pool 又继续使用的槽位读到的是同类型下一个合法值,是逻辑 bug 但不是内存corruption。规范还是草稿,几乎每周在变。
编译到 C,双向互操作
Goose 编译器输出单个 C 文件,本机有什么 C 编译器就用什么。extern fn hypot(x: f64, y: f64) -> f64 直连 libm,export "c_add" fn add(...) 反向暴露给 C 调用,内置 TinyCC 后端可以在编译器进程内即时编译运行,无构建步骤。每个可调整值住在 2GB 预留地址空间的数据栈上(--stack-reserve 16G 可调),--bce-lines 报告每行残留的边界检查,checkfree fn 在任何边界检查存活时拒绝编译,index 类型让图的边保留构造期完成的一次校验。
标准库 14 个模块全用 Goose 自己写;gfx(SDL3 GPU API 图形)、audio、physics(Box3D 刚体)、ui(Nuklear)按需从 git 拉 取;31 个示例从筛法、数独一路排到光线追踪、线程化 Mandelbrot、GPU 旋转立方体、迷你 Minecraft 和迷你 Doom。预编译版本覆盖 Windows x64、Linux x64 和 macOS(Apple 芯片与 Intel),VS Code 扩展带语言服务器。
3 万行 C++ 编译器的作者是 Claude Fable
README 的「History & Use of AI」一节写了这个项目的另一层实验性质:van Oortmerssen 数年前就完成了 Goose 的语言设计,但忙于游戏创业(跑在他另一门语言 Lobster 上)没时间实现,直到 Claude Fable 出现。他让 AI 克隆自己 Lobster 编译器的风格与结构,来回讨论补齐了原设计未定的细节,编译器实现、基准测试、示例和文档几乎全部由 Fable 完成,他本人负责语言设计与编码规范。选 C++ 实现的理由也坦白:Fable 在任何语言里能力几乎相同,Rust 的强护栏不再紧迫;编译器吐 C,身边本来就必备 C/C++ 工具链。
一个由 AI 写出主体实现的新语言,在自己基准里同时向 C++ 和 Rust 的最优实现发起比较,并把胜负数字一起公布,这件事本身比 1.19 倍这个数字更值得放进 2026 年的编程语言编年史。Goose 能否走出基准套件进入真实工作负载还是未知数,规范草稿每周在变,但「删掉堆、内联一切、窄链接、零标注安全」这条路线已经有了可复现的完整参照实现。