从 Java 迁移到 Go 后的想法

分享看从 Java 迁移到 Go 的人的经验,特别是在后端服务器端项目方面。

网友讨论:
我之前在做后端 Go 工作,现在在做后端 Java 工作。
构建项目很容易(Go 更容易),易于使用依赖项,并且易于运行测试。IDE 支持很好(Java 更好)。
总的来说,我更喜欢Go。但这些语言中的一种并不比另一种具有决定性的优势。

  • 我喜欢 Go 的错误处理。
  • 我喜欢并不是所有的东西都是一个类。
  • 我喜欢函数有多个返回值。
  • 我喜欢结构struct而不是到处使用构建器模式/流畅的接口。
  • Go 的标准库感觉更完整、更连贯(Java 有一些包袱)。
  • 浏览典型的 Go 项目要容易一些。

归根结底,这些只是偏好。我并不是不喜欢写 Java,我只是更喜欢 Go。

======================================================

我反向切换到 kotlin 和 spring。对我来说,问题不一定是语言本身,而是工具和生态系统。
Java 库/框架和 Kotlin 之间存在奇怪的交互(运行时可空性、Java 线程和协程混合)。我和我团队中的其他工程师一直在努力应对这些特殊的互操作怪癖,而且它时不时地困扰着我们。
我还发现与 Java 相比,Go 更容易阅读和导航 - 特别是在深入研究库/框架代码时。我发现 Java 代码往往有很多间接性并且难以理解,尤其是使用基于注释和反射的库。
我想这只是 JVM 生态系统带来的包袱让我想回到 Go。

=======================================================
老实说,使用 Java 工作 99% 的时间都是配置而不是实际编码。就我个人而言,我不喜欢 Java 框架(我正在使用 spring)的工作方式。
一切都像“魔法”一样。它无法让你控制事物,你几乎永远不知道事物在幕后是如何运作的。

========================================================
我与两者都进行过广泛的合作。与 Java 相比,我更喜欢阅读和编写 Go 程序的简单性
与混乱的 Maven(冗长,但一旦你学会了它)或 Gradle(呃 Gradle...,操他妈的 Gradle)相比,我非常喜欢使用 Go 依赖项、模块、编译。
Go 最大的胜利是摆脱了 Java 的遗留问题,即巨大的基于反射的框架,这些框架是模糊且难以调试的。
有很多企业 Java 文化往往会污染每个代码库,无论它开始时多么干净。

=========================================================

在 Java 中使用线程比在 Go 中调度 goroutine 稍微复杂一些。Java 在并发性方面表现出色(现在 Java 21 中有一个等效的绿色线程),但使用它们却不是那么简单。你需要考虑一些事情,比如执行器、池等。Java 的很多并发性都源于它在 90 年代的语言原始设计,当时它是开创性的东西。讽刺的是,Java 最初的线程模型是绿色线程,后来变成了完整线程,现在它支持这两种线程。

=========================================================

我对 Java 并发性没有做过多的研究,但我使用过 Completeable Futures。搬起石头砸自己的脚似乎更容易。如果您不处理运行时异常的所有可能情况,并且线程抛出异常,则它永远不会获得 GCd。我们在产品中运行这个应用程序会耗尽内存。
事实证明,如果没有在完整的Future链中使用异常,线程永远不会加入,并且只是一直运行在那里直到重新启动。
我确信还有其他方法可以避免这种情况,但没有任何迹象表明这是一个问题或根本没有问题。这在 Go 中不会发生。

=========================================================

我职业生涯的大部分时间都在 Java 上度过,现在转向 Go 并与其他使用 Java 的团队进行交互。虽然使用我不太熟悉的语法工作是令人沮丧的,但其他 Java 团队的存在确实凸显了我是多么喜欢 Go:

  1. Go 的依赖关系比 Gradle 或 Maven 简单得多。
  2. Go 中的并发性要好得多。我刚刚写了一些东西,在浏览数十亿条记录的同时,同时积累数百万条记录,老实说,我非常害怕 Java 时代的线程错误......它第一次在 Go 中完美地工作。与此同时,我要求另一个 Java 团队将他们的一些处理切换为并发(在 Go 中实际上需要一个小时才能发布 PR),他们给了我 3 周的估计,我查看了他们的代码,无法争论。

==========================================================

在我的工作中,我们将大部分新后端工作从 Java (EE) 切换到 Go。我们的一些 Java 微服务已经用 Go 重写,但大多数仍在运行和维护。
就我个人而言,与 Java 相比,我更喜欢使用 Go 工作,并且不愿意回到主要是 Java 开发人员的状态,在学习 Go 之前我已经做了十多年了。我已经害怕任何时候必须对 Java 进行更改,因为使用 Java 进行开发感觉笨重且臃肿。
当我们开始采用 Go 时,我们也在迁移到 Kubernetes。我们的 Go 服务仅使用 Java 服务的一小部分 RAM 和 CPU,这对于充分利用每个 k8s 节点非常有用。
切换的学习曲线有点粗糙。并不是因为 Go 很难学,而是我们必须学习在 Go 中适用的习惯用法、工作流程、库和模式,以及那些不适用的内容。我们还必须在 CICD、身份验证、日志记录、跟踪方面建立对等关系,以及编写和维护 Java 服务客户端的 Go 版本,以及在需要时编写 Go 服务的 Java 客户端。
可能花了一年左右的时间,我们才完全弄清楚最适合我们的项目结构和模式,并导致易于维护和可测试的项目遵循类似的模式,这样您在服务之间移动时就不会迷失方向。诚然,那一年主要是我在进行开拓性、POC 和奇偶校验建设,同时还致力于 k8s 迁移和其他工作。但后来我能够吸取经验教训并开始在 Go 上教授/指导/指导我的同事。
=================================================================

我是一名长期的 Java 开发人员,转而使用 Go 只是为了让我的生活变得有趣。Go 感觉就像是从其他代码表中粘贴的代码副本。有时会出现一个微妙的错误,它会被复制到各处。我怀念能够按我期望的方式工作的泛型。我怀念 IntelliJ 为 Java 提供的工具 - 我确信 Go 会赶上,但还没有。

我发现 Go 开发人员不喜欢“隐藏”实现层,因此作为维护者,我会接触到我所在层下所有内容的所有尖锐边缘 - 每个开发人员都会选择做出不同的权衡,因为一切都被暴露——这使得修复变得极其脆弱,因为也许一个人决定做一些不同的事情。