对 Go 和 Rust 的热爱吐槽!

发布: (2025年12月14日 GMT+8 01:38)
6 min read
原文: Dev.to

Source: Dev.to
Warning: rant!

引言

我已经受够了这玩意儿。每隔几周,就会有 Rust 爱好者爬到这里,摆出一副自以为是的 “但你尝试过无畏并发吗?” 的说辞,装作 Rust 是编程语言的第二次降临,终于把世界上所有的问题都修复了。新闻快报:并不是。它是一个臃肿、过度设计的烂摊子,伪装成万灵药,而它的并发模型是现代编程语言讨论中被夸大得最离谱的谎言之一。

Go 的并发模型

Go(以及在它之前的 Erlang/BEAM)实际上把并发做对了。

  • Goroutine 费用极低。
  • Channel 是内置且符合惯用法的。
  • 调度器 经受了实战考验。

你可以启动成千上万——甚至上百万——个并发任务,而不会让你的大脑崩溃,也不会让编译器大发脾气。它简单、可预测,并且可以在真实的生产系统中扩展,而不需要在生命周期注解上拥有博士学位。

Rust 的并发模型

Rust?哎呀。他们吹嘘 “无畏并发”,因为借用检查器在编译期捕获数据竞争。酷的故事,兄弟。但你猜怎么着?这只是一半的战斗——而且只是一小半。

真正的并发 bug 不仅仅是共享可变状态;还有死锁、活锁、饥饿、优先级反转,最糟糕的是:阻塞执行器

在 Rust 主流的 async 生态(Tokio、async‑std、各种时髦的实现)中,一切都是在线程池上的协作式多任务。一个傻瓜调用了阻塞函数——.await 一个暗地里执行 std::thread::sleep、同步读取文件,或调用了内部阻塞的 crate——,你就把整个运行时饿死了。你的 “高度并发” 应用在一个线程上卡死,而其余线程闲置。

这和 Python 的 GIL 或 Java 的线程阻塞废话完全一样。Rust 并没有阻止它;它只是让你手动去追踪它,包裹在 spawn_blocking 中,或者祈祷你的依赖库是彻底 async‑down 的(剧透:并不是)。

别再给我来那套 “但有 Send/Sync trait!” 的废话。Trait 并不会神奇地让第三方库变成非阻塞。只要有一个懒惰的开发者(或一个过时的 crate),你的无畏并发就和任何带 GC 的语言一样脆弱。

对比

方面GoRust
并发原语Goroutine、内置 channelFutures、async 运行时(Tokio、async‑std)
阻塞陷阱很难意外阻塞整个系统只要一次同步调用就容易阻塞执行器
编译期安全通过垃圾回收实现内存安全借用检查器保证内存安全
开发者体验编译快、单二进制、代码可读性高学习曲线陡峭、到处都是生命周期、async 样板代码冗长
典型使用场景服务器、后端、网络服务低层系统,需要零成本抽象且不想有 GC 暂停的场景

Rust 的借用检查器对内存安全很有帮助(恭喜,你在没有 GC 的情况下重新发明了 GC),但代价是要不断与编译器搏斗、在每个签名里写生命周期,以及让 async 代码变得 “染色” 且具有传染性,把整个代码库变成投针噩梦。

结论

Go 能把事儿做好。编译快、单二进制部署、乏味却易读的代码让新人几天内上手,并且并发真的让人愉快。Rust?学习陡坡、借用错误让你怀疑人生,还有一群传教士认为冗长 = 美德。

Rust 适合它本来的定位:低层系统,需要零成本抽象且不想有 GC 暂停。但对于服务器、后端、网络服务——也就是我们在 r/golang 里干的活——它是被夸大包装的过度设计。别再这里推销你们的邪教语言了。我们有 goroutine。我们有 channel。我们有可扩展的简洁性。

Go 才是王者。Rust 只不过是后排那个大声喊 “但我的所有权模型!” 的孩子。

给我点踩吧,Rust 党。我会在这里继续交付代码,而你们还在和编译器搏斗。

Back to Blog

相关文章

阅读更多 »