本篇内容是根据2024年12月份#339 Pitching Go in 2025音频录制内容的整理与翻译
过去十年中出现了如此多优秀的编程语言,其中许多都是专门构建的,Go 在何时何地仍然有意义,您如何在工作中证明它的存在?
Johnny Boursiquot: 大家好,欢迎收听新一期的 Go Time。我是主持人 Johnny Boursiquot,今天我们有一期特别的节目。我觉得这期很特别,因为在这个编程语言百花齐放的时代,我们要问一个问题:“Go 语言还有意义吗?” 在所有现代编程语言的变化中,以及考虑到过去人们对 Go 的一些抱怨、后来语言新增的功能、现在的生态系统,再加上人工智能的兴起等背景下,Go 语言是否仍然有它的意义?它是否还能像 10 或 15 年前那样重要?它还是云计算时代的语言吗?所以今天我们要讨论的是 Go 在当今时代中的地位。
今天和我一起参加讨论的是两位嘉宾,其中一位大家可能已经熟悉了。他之前来过几次节目,从讨论老派技术到聊人工智能都有涉及……欢迎 Kent Quirk 回到节目。Kent,你好吗?
Kent Quirk: 我很好,谢谢你。顺便说一句,我刚刚意识到,我已经用了 Go 语言十年了。
Johnny Boursiquot: 不错,不错。你的经验肯定能带来独特的视角。而且显然你之前也用过很多其他编程语言……所以我非常期待你的见解。另外一位嘉宾是 Christian Gabrielsson。 Christian,给大家做个自我介绍吧。
Christian Gabrielsson: 好的,首先,我想说一下 Go Time 的主题曲---
这是最棒的开场音乐之一,所以我很兴奋能参加这个节目。我在这个行业大约四年多,快五年了。我其实是后来才入行的。在我二十多岁的时候,我回到大学重新学习,然后转行。所以到现在我做这行大概五年了。其中有两年时间断断续续用过 Go,专业上大概用了一年半。后来换了公司……稍后我们可以深入聊聊这些事情。这就是我的背景。
Johnny Boursiquot: 太棒了,欢迎来到节目。能让我们节目的粉丝来到节目中总是很棒的。你听 Go Time 已经有一段时间了……如果你正在听这期节目,觉得“嘿,我也有些想聊的事情,我有些想法想表达”,欢迎联系我,我们看看能不能实现这个机会。
为大家提供一些背景信息,Christian 其实是通过提交节目提案和我们联系上的。当时---
这已经是超过一年前的事了---
你正在为你当时工作的公司团队提议使用 Go。后来我们取得联系时,你提案的项目最终并没有被采纳。我想知道,如果可以的话,你能不能和我们分享一些当时的情况。我们很少听到这样的故事:有人提议使用 Go,解释它的优点,但最后团队却没有采纳。所以我很想了解一些背景,为什么 Go 最终没有被选中。
Christian Gabrielsson: 好的,我之前工作的公司使用了一个平台……不知道你们有没有听说过,叫 MuleSoft。
Johnny Boursiquot: 嗯,他们已经存在一段时间了。
Christian Gabrielsson: 是的,糟糕,真是糟糕,非常非常糟糕。我对这个平台非常了解,甚至可以说对它的痛点了如指掌。我们用它构建了一个庞大的预订引擎,但这个东西启动需要 20 分钟。这对开发来说简直是灾难,因为它是一个无代码或低代码的解决方案。但问题是,就我短暂的行业经验来看,这种抽象层常常会失败。它的性能非常低下,开发体验也不好。
所以我想用 Go 创建一个 POC(概念验证模型),实现同样的 API。这些 API 非常简单。因为我当时为一家航空公司工作,所以 API 的功能基本就是从 Amadeus 或 Sabre(两个预订系统)中获取一些数据,对数据进行处理,然后以 REST 的形式返回。所以这真的非常简单,完全不需要用 MuleSoft 这种复杂的抽象工具来实现。
当我完成 POC 时,我的老板和老板的老板都非常兴奋。但是问题在于,“这个企业是否准备好接受这个改变?” 大家对 MuleSoft 的依赖非常深。而 MuleSoft 确实在平台层面提供了很多便利,比如安全性、流水线……所有东西都在一个盒子里。如果你想摆脱这个框架,尤其在企业环境中,你需要找到一种好的方式来实现,比如用 Kubernetes 等工具。而这对公司来说工作量太大,他们不愿意承担……这是可以理解的。
Johnny Boursiquot: 所以如果我理解正确的话,团队已经习惯了现有的平台,对新技术(无论是 Go 还是其他语言)的推动力不足以让团队放弃他们已经熟悉的技术。简单来说,引入新技术的成本太高。这么说对吗?
Christian Gabrielsson: 基本上是这样。比如说你想创建一个 Go 应用,并将其部署到一个公共服务上。那么,你需要一个网关,需要一个云平台来托管……你还需要解决所有这些问题。对当时的公司来说,这些在组织层面上太难实现了。
Johnny Boursiquot: Kent,你在这个行业里已经很久了……我是以最好的方式说这句话的(笑)。
Christian Gabrielsson: 我想知道你对 MuleSoft 的看法?说说看。
Kent Quirk: 我不想谈 MuleSoft。
Christian Gabrielsson: 好吧……
Johnny Boursiquot: 拜托(笑)。我相信你肯定遇到过类似的情况……这种技术选择有多少是文化因素造成的,而不是技术本身的原因?其中的细微差别是什么?你有什么见解?
Kent Quirk: 这是一个典型的问题,每当你尝试---
可以把它说成“如何自我迭代”。这是创新者的两难困境:“我现在有一个还算可行的方案。我敢不敢尝试用更好的东西代替它?” 如果处理不好---
坦白说,我也处理不好---
你可能会花很多时间进行转换,以至于等你完成转换时,市场已经远远落后了。
在其他情况下……我接触 Go 是在一个主要使用 Node.js 的组织里。当时还是在 Promise 出现之前,是 2014 年,我们深陷回调地狱。我们需要处理非常复杂的逻辑,普通人几乎无法理解,因为我们在处理 17 层回调。这简直是一团糟。有一个周末,我读到了一些关于 Go 的内容,心想“等等……”于是我决定尝试在周末用 Go 重写我们的一个服务。我们当时采用的是微服务架构。我在周末重写了整个服务,周一回来就说:“我们试试用 Go 吧,至少在后端。”因为 Go 的思维方式实在是简单得多。那时候大概是 Go 1.6 或 1.7,确切版本我记不清了,但已经是很早期的版本了。不过即便如此,我认为 Go 的设计选择还是使它成为了一个不错的选择。
回到更大的问题,每当……我现在工作的公司是 Honeycomb,专注于云环境的可观察性,我们试图取代市场上的竞争对手。我们进入客户公司,面对已经使用某个大牌竞争对手产品的用户,说:“嘿,我们可以做得更好、更便宜、更快。”无论我们当时强调的是哪个优势,他们都要权衡:“我已经投入了很多资源。” 问题是,你能否说服他们未来会比继续使用当前技术更好,即使要付出转换成本?你必须考虑这些问题。但有时候必须说:“是的,这值得一试。”
Johnny Boursiquot: 所以“更好”的定义……对许多公司来说,通常是与收入增加或利润增长相关的东西。仅仅作为一名技术人员,提出“我们应该切换到 X 语言,或者 Y 框架”,是需要付出代价的。虽然每个工程师都对新技术感到兴奋,但企业并不是每隔几年就更换技术的。所以必须有一个充分的理由……Christian 的情况让我想到,企业已经深度绑定到 MuleSoft,无论好坏。而现在有一名工程师提出一个可能技术上更好的解决方案,但运行到的问题其实并不是技术上的,而是商业上的。
Kent,现在 Honeycomb 使用了大量的 Go,但我相信你们也可能用到其他语言或技术,因为 Go 并不能满足所有需求。但如果你现在提出,比如从 Go 转到 Rust 或 Zig,你可能会遇到类似的阻力,对吧?
Kent Quirk: 是的,正如你提到的,这里存在几个不同的障碍。其中一个障碍是,“如果我们要转换……” 比如 Rust,这就是一个非常大的例子。很多人对 Rust 非常兴奋,原因各不相同。有些原因我认为很不错,但有些我并不感到兴奋,不过这也没关系。问题在于转换的成本,因为在采用新方法之前,你必须先重建现有的东西。当然,在某些情况下,比如“我们需要一个新服务”,那么我们可以尝试用 Rust 来写这个服务,看看效果如何。
实际上,我参与了 OpenTelemetry 项目,其中大部分底层工具,比如收集器等,都是用 Go 写的……可以说 Go 是 OpenTelemetry 的首选语言。当然,还有许多其他语言和组件,但现在有一个主要部分有人提议用 Rust 来写。所以我们现在有一个处理工具是用 Rust 开发的,而不是 Go……这也带来了一些团队层面的社会问题。比如,那些过去十年一直用 Go 工作的开发者,并没有足够的能力去审查 Rust 的代码。所以你需要让整个团队转变。这些确实有好处,但代价不容忽视。就像我之前提到的,当我带着团队从 JavaScript 转到 Go 时,我们还没正式上线,没有太多束缚。我们当时还在搭建所有的组件,准备上线。我们决定用 Go 转换服务,因为那时我们需要做的事情还不多,而转换后可以节省时间。
但对于 Honeycomb 来说,如果要从 Go 转到其他语言,比如 Rust,那几乎需要“国会立法”这样的重大推动了(笑)。原因很简单,Honeycomb 的代码量太大,并且大量代码正在稳定运行在生产环境中。仅仅因为某种语言“可能有一天会带来好处”而去切换语言,这是很难说服人的。
Johnny Boursiquot: 是的,这是很难说服的事情。那么 Christian,你提到你相较于 Kent 和我来说,在软件工程领域还算是新人。我记得你提到你大概有四五年的经验,对吧?
Christian Gabrielsson: 没错,差不多是这样。
Johnny Boursiquot: 那么以你目前的经验来看---
显然,你已经经历过尝试提出技术方案却未被采纳的过程,你也感受到了一点:尽管你的解决方案在技术上可能是合理的,但最终的决定往往并不完全基于技术。那么,迄今为止,你在软件工程旅途中还学到了哪些关于技术决策的经验?尤其是现在你换了公司后,你是如何看待这些的?相比我们这些已经做了很久的人,你现在的视角是怎样的?
Christian Gabrielsson: 我觉得其中一个让人沮丧的部分---
Kent 和 Johnny 你们都提到过---
是沉没成本谬误。如果一个公司已经在某种技术上投入了大量资金和时间,人们就很难放弃它。我认为 Kent 提到的某些情况对我来说是不可接受的,比如我遇到过一些开发者,他们非常喜欢 Java。而当我们要切换到 Go 时,他们就是不愿意学。他们对 Java 很熟悉,不想学习新语言。这种情况的确是阻力。如果你有一群人只愿意做他们熟悉的事情,那么要让他们切换到一些新东西就会更加困难。我在工程师中也见过这样的现象。对我来说,这很有意思,因为在我短短四到五年的行业经验里,我已经见识到了很多工具和语言的轮换。目前我主要在用 Airflow。
Johnny Boursiquot: 哦,Airflow。那么具体来说,它是什么?
Christian Gabrielsson: 是 Python。
Johnny Boursiquot: 好的。你能解释一下 Airflow 是什么吗?或者说它是一个什么样的技术框架或栈?
Christian Gabrielsson: 嗯,Airflow 是用来处理数据管道的工具。它是一个编排工具,最初由 Airbnb 开发,后来开源,现在归属于 Apache 基金会。所以它现在叫 Apache Airflow。它主要用于……比如在 American Express,他们用它来做很多事情。我现在在金融领域工作,所以我们用它来做报告,比如满足联邦要求和银行的财务报告需求。这是我现在的工作内容。但之前我用的是 Go,再之前是 MuleSoft(用 Java),再之前是前端开发,用的是 Angular。
在我看来,有太多不同的语言、工具和框架需要不断使用……我在短暂的职业生涯中学到的一件事就是,你必须不断地 a) 学习,b) 能够在不同语言之间切换。因为我认为这才是未来的趋势。
Johnny Boursiquot: 所以那句老话“为任务选择合适的工具”仍然适用……不过有趣的是,我的经验是,人们很少真正做到“为任务选择合适的工具”,最终往往还是选他们最熟悉的工具(笑)。在某些团队文化中,大家可能会接受这种现象,比如“我们选择了这种语言,我们做出了尽职调查,确定这是我们都喜欢并想用的语言”,于是这隐含地变成了“为什么不用我们已经决定要用的东西呢?”
Kent Quirk: 这也是为什么当初有那么多人采用 Node.js 的原因,因为人们会想,“我已经在前端用 JavaScript 写代码了,为什么后端不能也用 JavaScript?” 这在很大程度上也是我以前所在团队使用它的原因之一。但当你意识到前后端之间其实存在明显的分界线时,就没有特别的理由证明非得用同一种语言。而语言本身实际上是可以互换的,你可以在不同语言之间切换来完成任务。真正重要的是围绕这些语言的系统以及它们能提供的东西。Go 的一个重要优势就是它的生态。从我的角度看,Go 的最大好处是,如果我回头看我在 2014 年写的代码,我仍然可以用当前的 Go 编译器编译它。我可以读懂它,维护它。而当时的 JavaScript 代码,今天甚至无法运行,会被认为是过时了好几代的代码。而 Go 的一个主要优势就是它的长期可维护性。
Go 1.0 的兼容性承诺真的非常重要。十年过去了,我依然可以用相同的代码风格读写代码……要知道,软件的生命周期往往比你想象的要长得多。我有很多这方面的故事,但总之你必须能够持续维护它。而我们刚刚经历了团队从 React 16 升级到 React 18 的过程……这真的是一个痛苦的多月努力,需要好几个人参与。
Christian Gabrielsson: 很痛苦吧?我猜主要是因为像 Python 一样,有太多依赖关系。Go 通常没有这种问题。你不用像 npm 那样,确保所有的包都兼容,并且可以升级。
Kent Quirk: 通常是这样,Go 的依赖管理确实比其他语言好得多……不过 Go 也是花了很长时间才做到这一点。go.mod 最终算是一个不错的解决方案,但在 2017 年或 2018 年的时候,围绕依赖管理的争论确实是一场噩梦。
依赖问题确实让人头疼,特别是当人们说“是时候进行一次破坏性更改了”。如果你总是保持当前版本,或者你的模式是“我总是在写新前端,而不回头修旧的”,这可能不是什么大问题。但在后端开发中,代码的生命周期往往是永远的。
Kent Quirk: 通常情况不是这样的。有时这种情况仍然会发生,但总体来说---
是的,依赖地狱(dependency hell)在 Go 中不那么成问题了……尽管 Go 花了很长时间才达到这一点。最终 go.mod
的东西还算不错……但天啊,2017年或2018年那会儿,可真是一场噩梦。
不过,是的,依赖地狱确实是个问题。人们常常会说,“我们要做一个破坏性更改(breaking change),现在是时候做了。” 对于破坏性更改的接受程度,如果你总是保持最新版本,或者你的模式是“我总是写新的前端,不会回头修复旧的那些”,那么这种事情就会发生。比如移动端应用就是这样的情况。你开发一个移动端应用,维护几周,然后销量下滑,你就去开发下一个应用了。你真的不需要十年的可维护性。但当你在开发后端代码时,这些代码可能会存在很久很久。
插播广告:
Johnny Boursiquot: 所以在某个时间点---
或者说,我一直在想,那些对语言吹毛求疵的人,或者今天沉迷于自己最喜欢的语言的人。最终,我认为至少对我来说,很清楚的一点是……我觉得你之前也提过这一点,Kent---
最终,语言可能并不重要。一旦你为选择某种语言或技术打下了坚实的基础,在某种意义上,这个选择就不再那么重要了。因为当业务上线并开始盈利后,会有一个门槛,在这个门槛之上,任何收益或更改都必须是增量的。你不能回过头去更改已经在某种定义下“正常运行”的东西。你想新增的任何东西,都必须是新增的、叠加的,以增加收入或降低成本,无论具体情况如何。
当我说语言不重要时,我的意思是,你的注意力可能会转移。Christian,当你逐渐清楚地意识到这一点时---
组织甚至团队是不可能放弃 Java 和 MuleSoft 的,因为这些决策已经做出并定型了,你必须选择自己的战斗。而在这种情况下,你可能选错了战斗。
Christian Gabrielsson: 是的。而且不仅如此,我不知道我是否在邮件里提到过,但我后来转到了一家同一公司的另一个团队,这个团队实际上使用 Go。而我加入那个团队的原因之一---
有点有趣的是,我后来甚至领导了那个团队,尽管我对 Go 的经验并不多;他们只是知道我非常热情---
是因为那个项目简直是一团糟。并不是 Go 的问题……
Johnny Boursiquot: 是这个项目还是这个团队?
Christian Gabrielsson: 不是团队。团队里的开发人员都非常非常优秀。他们非常努力,也非常聪明。问题是,他们在基础层面上没有搞清楚如何让 AWS 和他们的产品配合工作。他们没有弄明白这些东西---
比如流水线(pipelines)。所以整个项目就是一团糟。于是就出现了对比。他们说,“MuleSoft 的东西虽然不那么令人兴奋,但它能用。而新东西 Go 就是一团乱麻,所以我们甚至不会尝试切换到它。” 我能理解。如果我是一个高管,我开始尝试---
我可以整天解释为什么这个不起作用,而那个起作用……但如果它不能提供价值,那它就没有价值。你懂我的意思吧?
Johnny Boursiquot: 那我们换个话题聊聊吧,聊聊我最近也在思考的一些事情。在我的工作中,因为我需要扮演多个角色,所以会遇到各种问题,这些问题并不总是能用 Go 来解决。有时我需要切换到 Python,因为我要做一些大型语言模型(LLM)的 AI 开发工作。有时我甚至需要写一些 Lua……不同的问题可能需要不同的工具和语言。但我发现自己越来越依赖现代工具,比如生成式 AI(gen AI)风格的大语言模型支持的聊天机器人,比如 ChatGPT 和 Copilot 等,来帮助我向前推进。这让我意识到,也许在这里,语言同样无关紧要……因为我试图完成的是解决问题。如果解决这个特定问题意味着我需要进入某个生态系统,比如用 Ruby on Rails 快速构建一个 CRUD 应用,作为一个能够很好地解决问题的概念验证(proof of concept),那我就会用这个技术栈……然后我可以用这些 Copilot 工具来帮助我生成代码。
昨晚我还在搞 Tailwind。我之前从未用过 Tailwind,但我需要快速制作一个静态网站,我心想,“好吧,Tailwind 似乎是个新热点,至少比我记忆中两三十年前用纯 CSS 的体验要好得多。” 所以我用 Tailwind,并让 ChatGPT 给我生成了一些 CSS。“给我一个模板,给我一个……随便什么。” 然后我复制粘贴,稍作修改,当晚我就完成了任务。我有了解决方案,发布了成果,然后继续做别的事情。
现在,我会每天都用 Tailwind 吗?不会。我有一个具体的问题,我用这些新工具解决了它。所以我想听听你们两个的看法,你们是否也感受到了一种从对特定语言或技术的狂热中脱离的趋势?现在我们有了这些 AI 工具,它们逐渐渗透进我们作为软件工程师、专业人士的生活中。你们是否也感受到这种转变,这些东西最终可能没那么重要了?
Kent Quirk: 我觉得世界比以前更加开放了,因为,随着互联网的爆炸式发展,如你所说,像 ChatGPT 和 Copilot 这样的工具,它们让切换工具和平台变得更容易了。我觉得这里有一个区别:“我需要解决一个小问题,我只想快速搞定,不在乎用什么语言,只需要一个解决方案” 和 “我要用这个来建立我的业务,雇用工程师来开发它,而且它将在未来的许多年里运行,可能还会以非常大的规模运行” 之间是有区别的。这些决定需要更多的思考。你需要考虑要选择的解决方案的优缺点。
比如,我喜欢 Python。我几乎所有的小项目都用 Python。对于很多事情来说,它是个非常棒的小语言。但我认识的所有在大规模使用 Python 的人,最终都会遇到巨大的问题。因为从 Python 的运行方式来看,大规模部署会面临很多困难。比如部署是个问题,全局解释器锁(GIL lock)是个真正的障碍……所以当你需要扩展到非常大的规模时,Python 会比 Go,或者 Java,或者 .NET 难用得多。这些系统就是为了解决这些问题而设计的,它们可以很好地工作。
所以如果你打算扩展到那个规模,我会非常质疑 Python 是否是正确的选择。但另一方面,Python 是一个很好的方式,可以让业务一开始就运转起来。所以也许值得忍受这些痛苦;这是个不错的问题---
如何扩展?然后可能是时候思考“我是否能用性能更高、可扩展性更强的语言重新实现部分后端?” 无论如何,我现在有点忘记我想表达的核心了。总之,这是大问题和小问题之间的决策。大决策需要更多的考虑,小决策没那么复杂。
Johnny Boursiquot: 那这种决策更多是围绕生态系统吗?还是因为行业认知?或者历史遗留问题?
Kent Quirk: 还有你能雇到谁。你可用的人才库,以及这些人认识谁,这都很重要。特别是在一个初创公司早期……你周围的人脉圈会产生影响。所以,是的,Python 可能确实是你的最佳选择,因为这些是你一直合作并成长起来的人才库,因此你可以稍后再处理那些问题。首先你得活下来。
所以是的,我觉得你可以选择一些让生活更轻松的语言,也可以选择一些让生活更困难的语言……这也取决于你所从事的行业……如果你在金融行业工作,你所能选择的语言可能和你在 SaaS 或游戏行业工作时不同。所以是的,所有这些因素……
Johnny Boursiquot: Christian,随着这些新工具的出现以及它们带来的便利,这对你作为工程师的生活有什么影响吗?
Christian Gabrielsson: 你是指 AI 辅助工具吗?
Johnny Boursiquot: 是的,没错。或许我可以问一个更具体的问题---
既然你一开始并不是 Airflow 的专家,可能也不是 Python 的专家,那么你是如何快速上手,足够胜任这份工作的?你有没有使用像 Copilot 或 ChatGPT 这样的新工具来帮助你快速学习?
Christian Gabrielsson: 当然有。我确实用了一些 ChatGPT……不过说实话,有些文档的质量好坏参差不齐。但对于 Airflow 来说,它的文档做得非常好。所以坦率地说,每当我接触一个新工具或新流程时,我喜欢先看文档……因为我知道有 AI 工具存在,它们确实很有帮助。我在工作中会使用 Copilot,我们有权限使用它。但我觉得仅靠 AI 工具学习某件事情是不够的。就像你提到的 Tailwind。是的,首先,关于 Tailwind,我用它构建过一个网站。我对 HTML 代码中的标记(markup)不太喜欢,但这可能只是一个不太受欢迎的个人观点……我更喜欢把 CSS 放在单独的文件中。不过我要说的是,当你学习某些东西时,就像我学习 Go 的时候,我读了两三本关于 Go 的书……因为我觉得你不能完全依赖这些 AI 工具来学习一门语言。你必须从根本上理解它的运作原理,这样才能有效地使用它。不过这可能只是我的观点,你明白我的意思吧?
Johnny Boursiquot: 所以,作为一个相对来说比较新的工程师,你仍然认为,从更深层次而不是浅层次去了解某种语言或工具,对完成工作来说是很重要的,对吗?希望我没有误解你的意思。
Christian Gabrielsson: 是的,百分之百同意。因为从根本上讲,如果 AI 能做我能做的事情---
那么我就没有存在的意义了。这就是资本主义的运作方式。
Johnny Boursiquot: 嗯,我的意思是,如果---
Kent Quirk: 你可以为电池的运行提供能量……[笑声]
Christian Gabrielsson: 如果 AI 工具能做我能做的事情,就没有人会付钱给我了。它应该是一个辅助工具。但如果我对一门语言一无所知,或者……总的来说,如果我不了解这些软件模式,那么这就有点像“盲人带着盲人走路”的感觉。
Kent Quirk: 有一个人,叫 Ryan---
我忘了他的姓氏---
他曾经创建了 Node,现在他又创建了 Deno,这是一个类似于 Node 的东西,拼写是 N-O-D-E 和 D-E-N-O。Deno 有一些非常有趣的功能,让它进入了我选择 Go 的一些领域。比如它可以编译成可执行文件,这点很酷……不过 Deno 也有 JavaScript 的问题,就是他们发布了 1.0 版本,挺好的,但我们从中学到了很多,现在他们在做 2.0。我前几天试着用 Deno 写一些代码,我本以为代码会很简单……但最后却变得非常复杂。因为所有示例以及 Copilot 的训练数据都是基于 Deno 1 的……
Johnny Boursiquot: 1.0……[笑声]
Kent Quirk: ……然后我试图做的事情全都被 Deno 2 标记为“这是过时的,你应该用另一种方式。”但我找不到任何关于另一种方式的示例……这就像 Christian 提到的,你需要用自己的头脑判断 AI 提供的内容是否有用。而在这种情况下,它并没有提供帮助。[笑声] 这也涉及到技术选择的问题。我觉得 Deno 2 看起来会很棒,但我打算几个月后再回头看看它的进展。
Johnny Boursiquot: 对,等尘埃落定再说。
Christian Gabrielsson: 说到 Kent 的观点---
我觉得 AI 工具最有用的地方是……我还没有深入研究它支持的更多代码库,因为我知道大家都喜欢用 Copilot 写测试。而我们都知道测试可以做到 100% 通过。但测试通过并不意味着它有用、可靠,或者有任何实际意义。所以当你偏离测试驱动开发(TDD),让 Copilot 来写测试时---
它真的在做有用的事情吗?它测试了你需要测试的内容吗?还是仅仅写了一个测试而已?所以对我来说,这仍然是一个悬而未决的问题,有点像“盲人带盲人”的场景。
Johnny Boursiquot: 最后一个问题,关于 AI 的---
冒险让这期节目变成另一期关于 AI 的讨论……Christian,对你来说,作为一名工程师,你还在不断成长,希望你能取得伟大的成就,并继续为这个行业做出贡献……你会担心 AI 的角色,以及它可能对你的职业发展轨迹产生的影响吗?
Christian Gabrielsson: 我可以用一个说法来回答这个问题:我是一个天生的斯多葛学派 信徒。斯多葛哲学的核心原则之一是,分清哪些事情是我能控制的(内部因素),哪些是我无法控制的(外部因素)。我已经换过一次职业了。如果需要再换一次,我想我也会去做。
我不认为 AI 会让我失业。我认为它会成为一种帮助工具。我不觉得软件工程师会消失,因为总有一些糟糕的代码库需要有人维护,总会有问题需要解决。从我在这个行业的短暂经历来看,那些低代码(low-code)解决方案似乎并没有真正奏效……但如果它们奏效了---
也很好。我一直说,当我退休的时候,要么去养鹅,要么开一家自己的潜水店。所以我不知道。我真的不知道未来五年甚至二十年会发生什么。说实话,担心这些事情有意义吗?一点意义都没有。
Johnny Boursiquot: 是的,这绝对是斯多葛的态度。没错,没错。而 Kent,如果同样的问题问你,我想因为你在行业中经验更丰富,按理说,你的职业生涯路径会有更多选择。现在 AI 在我们的职业中已经变得司空见惯,你觉得它对你有很大影响吗?它占据了你很多的思考时间吗?
Kent Quirk: 并没有。虽然我喜欢吐槽 AI,但我发现 AI 并没有解决我被要求解决的问题。我最近看到这样一句话,大意是“初级工程师写代码,高级工程师删除代码,资深工程师则消除系统或重新定义问题。”所以我觉得我们已经到了这样一个阶段:AI 可以写很多代码,但它写不出好的代码,也不知道它写的代码是否有用。
如果你能清晰地描述问题,可能可以让 AI 写出大部分代码……所以它可以成为一个有用的生产力工具。但我不认为它甚至接近于替代那些在可扩展组织中担任资深工程师的人。所以我并不担心。
Johnny Boursiquot: 对,这很有意思---
Christian,我知道你想参与进来……很有意思的一点是,一开始大家可能会说“嗯,我不觉得这足以取代初级工程师。”然后他们会说“嗯,我不觉得这足以取代高级工程师。”现在我们说“嗯,我不觉得这足以取代资深工程师。”
Kent Quirk: 我可不是这么说的……
Johnny Boursiquot: [笑着说] 不,不,我不是说你这么说了。我只是说---
但是拜托,拜托,给这个话题增加一点深度。
Kent Quirk: 我觉得这里的深度在于,我甚至不认为这东西(比如 ChatGPT)足以取代一个初级工程师。它可以被指示去写符合规格的代码……但是,制定一个 ChatGPT 能准确实现的规格,这仍然需要工程师的头脑。如果你要解决的问题非常简单,比如创建一个没人关心的普通 CRUD 应用,没有人关心可用性,没有人关心设计,也没有人关心它是否正常工作……如果你能以此为基础建立一个商业模式,那我祝你好运。但我不认为这是可行的。我想说的是,它确实可以提升生产力,但你仍然需要有人来“挥舞锤子”。它更像是一个更强大的锤子,但它不是建造者,也不是木匠。
Johnny Boursiquot: Christian,你想补充点什么吗?
Christian Gabrielsson: 那我接着说吧。那么 20 年后,你认为工程师会被取代,还是他们的角色会发生根本性的变化?
Kent Quirk: 我们这是要把这个话题变成一个 AI 播客了吗?
Johnny Boursiquot: 我们刚才承诺这是最后一个问题,但对,我们还是回到正题上来吧,在我们转向“unpops”(注:常指播客中的非主流观点讨论环节)之前。或许我们可以把 AI 的话题留到“不受欢迎的观点”环节再聊。我一直在思考 Go 的未来。Go 已经 15 岁了,并且还在不断成长……我觉得,就像 Java 一样,它现在已经达到了企业级别的标准,这一点应该没人会质疑。自从 Go 面世以来,它就是云计算的语言,并且仍然被用于几乎所有云原生服务、后端、子系统等工作……举个例子,可能 CNCF 项目中有四分之三以上都是用 Go 编写的,诸如此类。所以我们知道 Go 不会消失。就像之前的一些语言,比如 C、C++,还有 Java,这些系统仍然在支撑着现代社会的关键部分。这些东西不会突然消失。我觉得,我们总是需要那些了解这些技术的人……虽然有一段时间我们都在寻找那些---
我不知道我们现在是不是还在找---
但我们曾经在找那些仍然懂得写 COBOL 和 Fortran 的人,因为许多政府系统仍然在使用这些东西,这些主机系统。
所以我认为 Go 也会经历这样的循环:某样东西出现了,它变得流行,占据了大量市场份额,人们想要学习并使用它……然后它最终会被新的热门技术取代。但我觉得 Go 还没有到被新热门技术取代的阶段。我甚至不知道那个“新热门技术”会是什么。我觉得问题会被重新定义,借用 Kent 的高级工程师类比,我们会停止以传统方式定义问题,然后尝试用新工具以不同的方式解决问题,因为我们提出了不同的问题。但在此之前,Go 对于当前市场和未来来说都是合适的……你们怎么看---
你们现在选择 Go 的标准,还是像 10 年前、12 年前,或者在 Christian 你第一次接触到它时的标准一样吗?当时你看到它时可能觉得“哇,这太棒了……”你们现在选择或坚持使用 Go 的标准是否发生了变化?或者应该发生变化吗?
Christian Gabrielsson: 我觉得从根本上来说,这一直是选择工具箱中合适的工具的问题。Java 就是一个例子。JVM 冷启动需要几秒钟……所以如果你需要一个立即运行的进程,老实说,不要用 Java。但在这种情况下,显然应该使用更高效的工具,比如 Go,它没有冷启动的过程。
类似的,不是每个人都喜欢 Python,但对于数据科学来说,所有的库和生态系统都在那里,所以你完全可以用 Python。对于前端来说,那就是 JavaScript。我觉得这些事情不会经常改变。我认为 Go 的一个独特之处,是很多语言到目前为止还没有做好的一点,那就是向后兼容性。我觉得这会让它在未来的 10 年,甚至 15 年内仍然非常相关。正如 Kent 所说,你可以运行一个 5 年、10 年前用 Go 编写的项目,它仍然能正常运行。但如果我启动一个 3 年前用 JavaScript 写的老项目……我敢打赌它会出问题。对于可维护性来说,尤其是在大团队中,这一点非常重要,我个人是这么认为的。
Kent Quirk: 是的,我认为选择语言时有几个关键因素。正如 Christian 提到的,某些特定性能需求需要特定的工具。编译成二进制文件和运行在虚拟机上是完全不同的两回事。而像 Java 这样的虚拟机又和 Python 式的解释器/虚拟机不同……虽然“解释器”这个词不太准确,但你知道我指的是什么。
所以选择语言时,我觉得有趣的问题是……正如 Christian 指出的,Go 的向后兼容性意味着它的寿命会更长。没有什么“推动力”迫使你改变。而 JavaScript 的有趣之处在于,因为它变化太快了,所以到了某个时候你不得不做出大的改变。嗯,如果你无论如何都要为了维持 JavaScript 而做出大改变,那你可能会开始考虑是否有其他选择。比如从 Node 迁移到 Deno,或者干脆开始重写后端,因为旧的后端已经变得老化,你无法再维护它。这是一个非常有趣的转折点,而像 Go 这样的语言因为其稳定性而可以避免这种情况。
所以我认为 Go 仍然会存在。我是说,它在未来的 10 年、15 年内肯定还会存在。问题在于它会有多流行,以及是否会有人发明出一种稍有不同的范式,或者更重要的范式,或者其他什么东西?答案是我不知道。但无论是什么,我们都会去尝试,对吧?
片头音乐:
Johnny Boursiquot: 好了,谁带来了精彩内容?
Christian Gabrielsson: 首先,我得说,这个节目的主题---
无与伦比。我爱它,真的很喜欢。
Johnny Boursiquot: [笑] 不错。
Christian Gabrielsson: 我有一个酝酿已久的“不受欢迎的观点”。当某个团队选择使用“插入任意语言、工具或框架”来避免遭受大量痛苦时,我强烈建议大家先读一下入门指南,比如“你应该使用这个工具吗?它的适用场景是什么?不适用的场景又是什么?”因为即使我当软件工程师的时间不长,我已经太多次看到工具、框架或语言被用在不适合的问题上。所以我的“不受欢迎的观点”就是:读一下入门指南,90% 的问题能解决。[笑声]
Johnny Boursiquot: 你会以为这不会是一个有争议的问题,但我们这些工程师就是喜欢直接动手,撞得头破血流……答案明明就在 readme 文件里,但不,我们非得先经历点痛苦……[笑声] Kent,你有什么想法?
Kent Quirk: 我想接着刚才的话题说……我认为 Go 在复杂性和语法支持方面处于一个很有趣的位置。它一直被批评为过于“极简”,但我认为这其实是它成功的关键之一。无论是像 Haskell 和 OCaml 这样的语言,还是像 Rust 这样更现代的语言,它们都很难维持长期的生产使用。它们确实会吸引短暂的关注,但却很难在生产环境中持续流行。原因就在于它们技术上太复杂了。要正确使用这些语言需要耗费过多的脑力。你无法用这些语言随便写一些糟糕的代码然后碰巧成功。因此,这意味着你必须从顶尖工程师中挑选人才,而从长远来看,这种模式是无法扩展的。如果你想建立一个能够大规模扩展的业务,你需要更多普通水平的工程师。因此,这些语言很难真正获得可持续的吸引力。
Johnny Boursiquot: 我的“不受欢迎的观点”是我最近才得出的。如果你还记得,早些时候很多人对 Go 的抱怨之一是,“哦,它没有泛型”或者“它没有---
”插入你最喜欢的语言中的你最喜欢的功能,诸如此类的抱怨。或者他们不喜欢它的错误处理方式。这些通常的批评……其中一些你现在已经听不到了,因为这些功能已经被加入到了语言中。但我的观点是,除非你有非常特定的需求需要使用某些语言特性,比如泛型、迭代器或者类似的东西。如果你发现自己并不经常需要使用这些东西,尽管它们受到很多关注和宣传,这并不意味着你做错了什么。如果你在使用 Go 时没有用到迭代器,这没有问题。
我认为这些特性非常适合解决某些特定类型的问题。如果你需要创建抽象或某种通用工具来处理不同类型的数据,那么这些特性会非常有用。这些“泛型”---
这里用这个词稍微宽泛一点---
解决的是一类特定的问题。但如果你的日常开发工作只是为了处理业务逻辑,比如把数据从一个地方移动到另一个地方,而你并没有经常用到这些特性,甚至没有考虑到这些特性,这完全没问题。这只是意味着你的使用场景不需要它们。就算语言里有某个功能,你不使用它也完全可以。这没有任何问题。如果你从来没有在代码中用到泛型,因为你不需要它,那没问题。如果你用更长的方式来解决某些问题,那也没问题。如果你从来没有用过迭代器,那也没问题。如果你从来没有用过模糊测试,那也没问题,因为不是每个语言特性都需要被使用。
归根结底,这还是关于为任务使用正确的工具。我很感激 Go 提供了这么多工具,让我可以在一个工具箱中找到我需要的东西,然后根据特定的需求去使用它。我为此感到感激。但如果我并没有经常使用某些专用工具,因为我很少有需要使用它们的场景,这也没什么问题。知道这些工具存在,并且知道如果有需要时我可以使用它们,这就足够了。我不会因为自己没有使用某个特定工具而觉得“哦,我没有充分发挥这门语言的潜力”。
Christian Gabrielsson: 在 Go 中,泛型真的有用吗?
Johnny Boursiquot: [笑]
Kent Quirk: 是的,我的意思是……Go 中的泛型只是其他语言试图通过所谓的泛型解决问题的一个子集。在 Go 中,它基本上是把类型作为参数。所以,比如说我想创建一个容器……最近我需要构建一个集合(set),它能为存储在集合中的元素设置生存时间(time to live)。我写了一个泛型实现,因为用泛型写出来和为 int 或 string 专门写几乎一样简单。所以,我可以创建一个泛型版本的**[听不清 00:58:12.01]**。尽管在我的具体应用中它可能只用了一次,现在它变成了一个工具库中的一部分,其他人也可以使用它。这是值得的。这就是泛型的一个用例。但你需要小心,我也见过一些情况,就是为了避免写两次同样的四行代码,有人写了四行泛型代码和 100 行注释。那就有点过头了。
Johnny Boursiquot: 是的。我觉得这是高级工程师会指出的内容,或者资深工程师会对初级工程师指出的内容。而 AI 可能会很难判断什么时候应该用某种方式,而不是另外一种方式。所以在这里需要更高层次的思考,去理解短期利益---
“哦,这看起来很酷,非常狡猾,非常聪明的代码”---
和长期可维护性之间的平衡。如果你凌晨三点接到一个报警电话,需要看这段代码……你会感谢哪一种写法?
好了,好了……我感谢你们两位参与节目,讨论了这个略带细微差别的话题。这个话题一次又一次地被提起,Go 对比---
插入某些语言或技术。这次我们听到了一个资深工程师的视角,也听到了一个相对新工程师的视角。我希望所有的听众也有自己的“啊哈时刻”。如果你有,请在社交媒体上留言告诉我们你对内容和“不受欢迎的观点”的看法。
好了,谢谢你,Christian,谢谢你,Kent,感谢你们来参加节目。
Kent Quirk: 很高兴能参与。
Christian Gabrielsson: 非常感谢。我很感激。