从Java转Go的个人体会

这里仅从一个业务开发的角度谈谈体会,格局较低,仅做个人记录
编程语言是程序员接触和使用最多的工具
后端技术基础的深度是快速学习和适应新语言的关键

  • 基于对工作中接触过的几种编程语言及其部署架构的看法继续聊。

  • 截至目前,职业生涯五分之四的时间都是在使用Java。出于个人意愿和兴趣,以及行业的发展形势,也系统的自学了Go语言,并在个人的小项目实践。在一次意外的组织变动中,我转岗到了新团队,并开始使用Go,由于之前自己的自学基础,基本是无缝切换到新语言。可能是由于团队人员大部分是从Lua或PHP开始转Go的,在那里甚至感觉自己稍稍领先。

  • Go抽象业务比Java麻烦,代码不美观,但是它原生高并发,而且微服务下很多时候就一个后端服务,业务足够小,不需要复杂的设计模式等,并不需要像以前写大型Java应用这样做非常多的抽象,还能打二进制包,甚至还能保证一个团队所有人代码都是相同风格

  • 以下讲一些个人看法,比较乱甚至不正确,仅做个人记录

    1. 小型项目省内存
    2. 写命令行程序方便简单
    3. 现在绝大部分功能都有相应的官方库和开源库
    4. 运行无需环境依赖,直接打包成二进制可执行程序(Java现在也可以了,可能大部分业务场景下体积还较大)
    5. 支持交叉编译,不要特定平台
    6. 打包体积小(根据代码实际使用情况打包-这点是我一直苦苦寻找的)
      • Go语言中有未用代码消除和可执行文件瘦身机制。只有在程序执行路径上被调用的函数才会进入最终的可执行文件,未被调用的函数会被消除
      • Go未用代码消除与可执行文件瘦身
  • 为什么现在大多数人都会认为Java启动慢占内存呢?

    • 首先不是Java自身的原因,而是跟实际使用场景有关
    • 使用Java大多数用来做业务开发,也习惯引入很多依赖库,首当其冲就是SpringBoot等框架
    • 多数都是spring相关类、proxy/cglib,以及各种bean配置
    • 而且很多类都是在启动的时候初始化的
  • 微服务下的编程语言

    • 在K8S流行之前,Java通常是使用SpringCloud
    • 其实微服务相关技术,在K8S已经实现了
    • 无论是使用Go还是Java,目前都应该向K8S靠近
    • 还有一点,K8S本身就是用Go实现的

扩展

  • 体验Graalvm+SpringBoot+Java21构建原生程序

  • 在内存利用效率上,Go语言确实比Java做得更好,在4个不同的角度来总结

    1. Java的JIT策略比Golang的AOT策略
      • Java在运行时相比Golang多占用了一些内存。原因在于:
        • Java运行态中包含了一个完整的解释器、一个JIT编译期以及一个垃圾回收器,这会显著地增加内存。
        • Golang语言直接编译到机器码,运行态只包含机器码和一个垃圾回收器。
      • 因此Golang的运行态相对消耗内存较少。
    2. 内存分配和垃圾回收器
      • Java确实在起步占用上偏多,毕竟jvm需要更多内存做jit,默认的gc算法对内存要求偏高,但这不能代表后续占用仍然线性增长。如果目标是启动成百上千个内存需求较少的进程,那Java确实不擅长。
    3. 并发
      • 协程模型比线程模型更加节省内存。
    4. 反射
      • Golang的反射更加简单,导致框架的内存消耗Golang程序比Java程序优秀。主要是因为: Java的框架实现中大量使用反射,并使用hashmap缓存信息,这2个都是极度消耗内存的行为。 Golang的框架中也使用reflect、map。但是Golang是面向interface和值类型的,这导致Golang的反射模型要比Java的反射模型简单非常多,反射过程要产生的对象数量也少非常多。
  • 为什么一些已经选择 Java 的公司,现在又开始考虑使用 Go?

    • 为什么要用Go重写Dubbo?
    • 相较于 Java,Go 在启动速度、编译速度、内存使用和高并发(如协程)方面都有明显优势。所以,那些已经采用 Java 的公司现在也在考虑引入 Go。但要注意的是,目前这样的公司仍然是少数。另外,一些公司并没有严格规定技术栈的选择,因此新成立的部门或新业务团队可以自由选择,而他们可能更倾向于选择 Go 作为开发语言。
    • 小结: 总的来说,无论是选择 Java 还是 Go,都是有其合理性的。一家公司同时选择这两种语言也同样合理。尽管这样的公司占比不大,但 Java 与 Go 之间的交流需求仍然存在。