Express作者TJ告别Node.js转向Go:关于性能、可用性与错误处理的思考
Express作者TJ Holowaychuk发文宣布告别Node.js并转向Go语言。文章指出Node.js在分布式系统中性能虽高但可用性不足,特别是错误处理机制存在缺陷。TJ认为Go语言在并发、类型重构及标准库方面更具优势,同时呼吁Node.js社区关注可用性与健壮性,通过引入generators等机制改进核心体验。
引言与译者说明
本文翻译自TJ发布的《Farewell Node.js》。阅读后我深受触动,但并未完全认同其所有观点。例如,我认为Node.js的npm包注册中心是其显著优势之一,而Go在此方面相对薄弱。受限于个人水平,翻译过程中遇到诸多难点,我曾通过作者博客及StackOverflow求证并获取解答。译文难免有疏漏之处,恳请指正。
PS. 作为一名Node.js初学者,感谢TJ的贡献,祝好。
正文:
告别Node.js
离开Node.js领域
告别Node.js:维护与现状
我在生产环境中使用Node.js的时间足够长,不幸的是,既然我已不再享受这项工作,至少此刻,这是我的正式告别。更重要的是,我需要项目维护者。
Node.js在某些方面确实出色,但对于我近期感兴趣的软件类型,它终究不是合适的工具。我仍计划使用Node.js开发网站,但若你对维护任何项目感兴趣,请在GitHub上留言,提供你的GitHub用户名、npm用户名及项目名称。通常我只要求你不彻底改变现有API,若必须改变,建议开启新项目。
Koa是我将继续维护的项目(与Co及其他朋友一起)。
圣杯的故事
转向Go:圣杯与分布式系统
我一直深爱C语言,但每个C开发者都知道它有价值却易出错。在日常工作中证明语言选择的合理性很难,因为它并非总是最快的工作方式。简洁性是其赞美点,但没有大量模板代码难以走远。
随着参与分布式系统开发增多,Node.js性能高于可用性与健壮性的趋势让我日益沮丧。过去一周,我用Go重写了一个大型分布式系统,其健壮性、性能更优且易于维护。由于同步代码通常更优美且易于开发,它拥有更好的测试覆盖率。
我并非说Go是圣杯,它并不完美,但对于当今多种语言而言,Go对我是一个极好的答案。随着Rust和Julia等“次世代”语言逐渐成熟并找到定位,我相信我们将拥有更多伟大解决方案。
我个人对Go感到兴奋,因为其迭代速度快。很高兴看到他们渴望达到2.0版本,据我所知,他们并不害怕打破原有的美好事物。如果是真的,我很乐意接受,因为我相信有益於语言的事应快速推进。但我并非运行大量系统的软件巨头。:D
编注:我可能误读了某些邮件列表提交,他们任何时候都不渴望做出破坏性改变。@enneff
为何选择Go语言
为什么是Go?
如果Node.js对你有效且无需担心,它仍是好工具。但若有些事困扰你,别忘了跳出盒子看看外面——在最初几小时使用Go构建产品时,我便被吸引。
再次声明,我并非说Go绝对是最佳语言且你必须使用它。但就其年龄而言,它非常成熟健壮(大致与Node.js同龄)。类型重构有趣且简单,Go提供的作业和调试工具很棒,同时社区拥有关于文档、格式、基准及API设计的强大条例。
在极度习惯Node.js的高模块化并体验过Ruby标准库腐烂后,初次听到Go时,我认为其标准库糟糕。深入后我意识到现阶段大部分标准库很有必要,如compression、json、IO、buffered IO、字符串操作等。大部分API定义良好且强大,仅使用标准库即可编写整个程序。
Go的第三方包生态
第三方Go packages
大部分Go库看起来相似,我使用过的第三方代码质量很高。而在Node.js中很难找到这些,因为JavaScript吸引了不同技巧层次的开发者。
Go没有包注册中心,因此你通常会看到5或6种相同的包。有时这会造成困惑,但它有一个有趣的副作用:你必须通过认真审查每个包来决定哪个是最佳方案。Node.js通常有规范包如“redis”、“mongodb-native”或“zeromq”,因此你会停在那里并推断他们是最好的。
并发与错误处理对比
如果你从事分布式工作,会发现Go令人印象深刻的并发基础数据类型非常有帮助。我们可以通过Node.js中的generators获得相似功能,但在我看来,generators仅做到一半。没有独立的错误处理,即使最好也仍是平凡的。当这些方案都能良好运行时,我也不想等待社区三年去重整。
在我看来,Go的错误处理出众。就你必须考虑每个错误并决定怎么做而言,Node.js很棒。然而Node.js失败在:
你可能会重复进行回调
你可能根本不会进行回调,迷失在不稳定状态中(译注:例如忘记传递错误处理回调,错误时,Node.js将吞掉这个错误而没有任何反馈)
你可能会得到外带的错误
emitters可能会获得多个错误的事件
忘记错误的事件处理会毁掉一切
经常不确定什么需要错误处理
错误处理非常冗余
回调烂透了 在Go语言中,当我的代码结束时,它就结束了,你不能在语句中重新执行。在Node.js中这是不确定的。你会认为一个程序完全执行完毕,直到一个库意外多次调用一个回调,或者没有正确清除handlers然后引起代码再次执行。在实际生产代码中找到这些原因相当困难,为什么要烦恼这些?其他语言不会让你经历这些痛苦。
对Node.js未来的展望
未来的Node
我仍然希望Node.js做得很好,许多人对其进行了巨额投资,它确实有这样的潜质。我认为Joyent和团队需要关注可用性——如果你的应用很脆弱且难以调试、重构及开发,性能是无意义的。
在4-5年内我们仍将有着这种模糊不清的错误“Error: getaddrinfo EADDRINFO”,这个事实告诉我们Node.js的发展优先级在哪里。可理解的是,当你专注于建立系统核心时,很容易漏掉这些东西。但我认为用户已经对这类事物一次又一次表达了意见却没看到任何结果。对于声称说我们拥有的已经是完美的,我们通常获得少数的回应。在实践中,却并非如此。
streams是被中断的,回调不容易使用,错误含糊不清,工具并不好用,社区条例是有,相对于Go而言却显得匮乏。尽管如此,一些特定任务我仍可能继续使用Node.js,比如创建网页,或者一些零散的API或者原型。如果Node.js可以修复一些它的基本问题,那么它有机会保持相关性,但当存在另一方案是更高的性能和更高的可用性的时候性能高于可用性的论证不会走的太远。
如果Node.js社区决定去拥抱generators并能在Node.js非常核心的地方实现他们,去适当的传递错误,是有机会让这个是可参照的。这会彻底的提高Node.js的可用性以及健壮性。
好消息是,不久之前我跟在StrongLoop里面的贡献核心代码的并充满天赋的家伙聊过。他们正在明确的采用通过倾听开发者对这个平台的回复,并且计划找到修复这些问题去修复的正确方式让未来的Node.js更加易于工作。我不确定多家公司对核心部分同时开发的冲突会如何结束,但我希望开发者驱动方会胜出。
这并不意味着这是一个对个人的攻击,很多真的有天赋的人们正在与Node.js或在Node.js之上工作,但这再也不是我感兴趣的地方了。我在Node.js社区中经历了一段伟大时光的同时也遇到了一些真的很有趣的人。
故事的寓意在于,不要被你自己的圈子所限制住!看看其他地方有什么,你也许会再次享受编程。在这之外还有很多了不起的解决方案,我犯的错在于等了太久才去与他们一起游戏!
怎么在本地运行JavaScript脚本:Node.js下载安装与环境配置教程
2026-11-05 09:02:33
JavaScript开发环境怎么搭建:Node.js安装与VS Code配置指南
2026-11-03 23:36:59
JavaScript零基础入门:环境搭建与第一个Hello World
2026-11-03 23:34:09
NW.js 是什么:基于 Chromium 和 Node.js 的桌面应用框架
2026-11-03 15:14:00
nvm、n 和官方安装包:哪种 Node.js 升级方式更适合你
2026-11-03 14:54:28
