老骥伏枥志在千里,烈士暮年壮心不已。
-- 致Java
大家好,我是Coder哥,今天我们来聊一下Go 和Java,本篇文章主要是想给对后台开发的初学者和有意向选择Go语言的有经验的程序员一些建议,希望能帮助各位自上而下的来了解一下Java和Go的全貌。
作为一个多年的Java后端开发,用的时间久了就会发现Java语言一些问题,所谓婚前风花雪月,婚后柴米油盐,当年那些吸引我的优点,现在在我看来已经成缺点。而这个时候Go出现了,它带着更好的背景,更便利的语法,更快的速度来了,之前怕它乱来,但是也怕它不来,现在它来了,来的正当时。
当年Java凭借着跨平台和自动GC,并借着互联网的东风,迅速蹿红,并在移动互联网时代彻底爆发,随着多核处理器的普及和云原生的到来,Java的问题也逐渐显现:
- JVM的臃肿。
- 高并发下由于语言级别的
内核线程模型
带来的性能问题。 - 代码的复杂性。
- 复杂的继承关系。
- GC回收的瓶颈等。
而此时Go这个天生并发、语法简洁跨平台的语言初露锋芒,在这个并发时代,Go如鱼得水,回想当年Java的如日中天,彼时彼刻恰如此时此刻。
接下来我们从多个维度对比一下Go和Java,
为什么要比较它们?
随着越来越多的后台Java应用转移到Go, 我觉得有必要来深入的聊一聊这两个语言了,我们从语言层面(语言特性、速度和易用性、内存使用等方面)
、社区活跃度
来PK一下,进而总结出这两个语言的优缺点
以及这两个语言的开发方向
,并给各位正在纠结下个项目要不要用Go的开发者一些建议
。
一、语言层面
1. Java vs Go 语言特性
简洁性
Go 是一种极简主义语言,是一种静态类型、编译、多范式和通用的编程语言,正式的Go 语言规范只有 50多页,有很多例子,而且相当容易阅读,这使得学习语言和阅读和编写程序变得更容易。
而Java® 语言规范目前有700多页。大部分复杂性是由于持续扩展或添加新功能造成的。
Go 和 Java 都是 C 家族语言,所以它们具有相似的语法。因此,Java 开发人员可以很容易读懂 Go 代码,反之亦然。Go 不需要在语句末尾使用分号(;
),只有少数情况例外。相对来说说,Go 的行分隔方式更清晰,更易读。
面向对象
Java是面向对象的语言,有完整的继承体系,方便的实现多态的机制,能灵活的构造可重用性和易维护性的代码,并且通过OOP能简洁的实现反射机制。这些特性非常符合构造复杂的项目,但由于复杂性同时也导致编码的成本提升。
比如Java的反射实现就很简单,他只需要获取类中的信息就可以:
代码语言:javascript复制Class clazz = o.getClass();
Constructor cs = clazz.getConstructor();
Method[] methods = cs.getDeclaredFields();
而Go不是面向对象的,它没有传统意义上的继承或反射,构建系统通过组合和嵌入结构体的方式来实现,也就是所说的鸭子类型,多态也是通过接口来实现的,Go 没有类的概念,并且结构体只包含了已声明的字段。因此,我们需要借助“reflection”包来获得所需的信息:
代码语言:javascript复制type Foo struct {
A int `tag1:"First Tag"
tag2:"Second Tag"`
B string
}
f := Foo{A: 10, B: "Salutations"}
fType := reflect.TypeOf(f)
switch t.Kind(fType)
case reflect.Struct:
for i := 0; i < t.NumField(); i {
f := t.Field(i)
// ...
}
}
虽然这不是一个大问题,但由于 Go 中没有结构体的构造函数,所以很多原始类型必须单独处理,并且需要考虑到指针。在 Go 中,我们可以进行指针传递或值传递。Go 的结构体可以将函数作为字段。所有这些都让 Go 的反射变得更加复杂。除此之外,虽然整体上灵活度不如Java,但是它易于编写和维护。
并发性
Go 作为一种为现代多核计算机设计的语言,简单优雅的并发,并且具有强大的并发模型,其设计基于两级线程模型改进的GMP模型,这样能大大减少并发切换线程的性能开销,而且这些模型统一封装到语言级别的调度层,只需通过关键字 go
就可以开启协成,提高了易用性。
Java语言上没有协成的概念,Java的线程模型依然用的内核级线程模型,多线程开发依然需要复杂的实现,而且实现方式有很多种而不用拖着一个像,你需要了解每种实现方式的优缺点才能写出高性能的代码,除了这些还需要了解各种锁,来保障你写的线程是安全的。具体可以看之前的一篇文章线程的实现方式
垃圾回收
Go 的主要功能之一是垃圾收集,尽管 Java 也有垃圾收集,但它并没有Go的那么快,虽然随着G1和ZGC的出现缩短了与Go的差距,但显然Go更擅长管理内存。它不包含引用链接,而是包含指针,而且Go的垃圾收集器经过大量优化以防止STW。整体上Go的垃圾收集方法更精细。这点我们后面会出单独的文章来详细聊聊
除了以上的语言特性,还有:
异常: Go 不使用异常,而是使用错误(error)来表示诸如文件结束之类的事件,并使用运行时恐慌(panic)来表示运行时错误,例如尝试索引数组越界。
泛型: Java的泛型通过类型擦除来实现,使一些代码更清晰,但是不支持泛型数组,并且具有上限和下限的类型通配符等,这让编码变得很复杂。而Go泛型没有Java的复杂,它有一些内置的泛型数据类型,比如,切片和map等,使用起来比较方便清晰易懂。
安全性: Java语言本身并不能保护你免受漏洞的侵害,但它的某些功能可以使您免受常见的安全漏洞的侵害。比如没有指针能避免一些未经授权的访问内存操作。其次Java有不同权限的访问修饰符,为每个应用程序创建不同级别的访问权限。从 Go 1.13 开始,go 命令默认使用 Go 模块镜像和 Go 校验和数据库下载和验证模块,语言层面内置安全策略。具体可查阅Go Module 镜像、索引和校验和数据库
2. Java vs Go 编码的速度及容易性
Java自1995年以来一直存在,它还用于很多设备,而且由于它的向上兼容性,导致了很多功能本可以基于新的标准重新实现以提高性能,但恰恰因为兼容性让他放弃了这些,所以有很多功能效率依然是之前的标准编写的。
而Go是没这个问题的,因为它的库要比Java小的多,而且是按照现代的标准编写的,因此性能上更胜一筹。
由于Java的语法标准比较多样化,导致每个程序员写出来的Java代码都有不同的风格,而Go从设计之处就考虑到这一点,Go的代码更加的简洁和紧凑,它删除了不必要的括号和一些多余的符号,这也减少了出错的概率,更加的易于编写。
所以在编码速度和易用性上Go更胜一筹。
3. Java vs Go 跨平台性
众所周知,Java是JVM平台的语言,一处编译处处运行,这个是Java引以为傲的优点,但它的运行时环境必须在JVM上,这就导致了Java运行时的臃肿,浪费了一部分资源。
而Go通过编译成可执行文件巧妙的解决了这个问题,虽然它不是跨平台性语言,但它在编码器层面依然可以实现一套代码编译出不同平台的执行文件,可以直接在各个平台上运行,而不用拖着一个像JVM一样的运行时环境。
Go运行时环境就是系统环境,而Java还需要一个虚拟机环境(JVM), 所以在这一点上我觉得Go这种是比较好的。
二、Java vs Go 社区活跃度
Java已经存在了很长时间,几乎所有的web开发、后台开发、Android开发都在使用它,成千上万的人活跃在Java社区并提供大量的开源支持,对于后台开发有着一套完整的解决方案,比如,spring体系可以构建出一套高性能且稳定的服务。
而Golang算是个新项目,虽然社区一样很活跃,但依然弥补不了它资源匮乏的事实,虽然对于后台开发也有整套的方案,但它还远不足以匹敌Java。
其实除了上面这些维度,还有很多维度,比如泛型,异常,函数式编程等语法特点,这些我们就一笔带过了,那么基于以上的比较我们可以总结一下这两个语言的优缺点:
三、优缺点总结
Go的优点
- 代码简洁性
- 静态类型可编译成机器码直接运行
- 天生多核并行
- 垃圾收集
- 跨平台且不依赖运行时环境
- 简洁的泛型
- 内置安全性
缺点
- 有限的库支持
- 泛型不够完善
- 灵活度没Java高(这个可算优点也可算缺点)
Java的优点
- 优秀的文档
- 优秀的三方库
- 多线程
- 灵活性高
- 平台独立性
- 完善的语言特性
- 垃圾回收
- JVM
缺点
- 垃圾回收效果不佳
- 大量冗余的陈旧实现导致性能不佳
- 代码的复杂性
- 复杂的继承机制
四、开发方向
没有一种语言适合所有的工作,但有些语言比其他语言更适合更多的工作。
Go 最适合开发以下类型的应用程序
- 分布式网络服务:Go 的内置并发特性,主要是 goroutine 和通道,非常适合开发一些网络服务。因此,许多 Go 项目用于网络、分布式功能和云服务:
Web 服务器
、API
、应用框架
、分布式存储服务
等。 - 云原生开发:它的并发和网络能力,以及高度的移动性,使其适合构建云应用程序。事实上,Go 已被用于构建云计算的多个流行项目,包括
Docker
、Kubernetes
和Istio
等。 - 区块链: 由于Go有着非常好的性能,并且简洁的语法,现在它是区块链开发的首选语言。
- 其他:一些基础设施和独立的工具等,比如SSH服务器,
Java开发的方向
- 后端服务:Java spring 有着完善的微服务体系,常用于后台服务的开发。
- Android应用:尽管Kotlin已上升为Google的亲儿子,但他和Java很相似,都是JVM语言,而且Android的SDK依然是JAVA。
- 大数据程序:Hadoop 是用 Java 编写的。Scala、Kafka 和 Spark 都使用 JVM。此外,Java 使您可以访问许多经过验证的库、调试器和监控工具。
- 金融项目:作为金融行业最受欢迎的语言技能之一,Java 被用于服务器端和客户端来构建可靠、快速和简单的网站。它也是建模和数据模拟的首选语言。
五、对开发者的建议
Golang vs Java:哪个更适合初学者?
Java和Go都是高级语言,相比于C 、C有更好的可读性。Java是面向对象的,一种基于对象和行为而不是功能和逻辑组织的软件模型,并且OOP可以提供极大的可重用性和效率,相对于Go可能比较难上手。而Go语言语法简洁并且是一个比较新的语言,对初学者更加的友好。
结论: Go 更适合初学者,并且被认为比 Java 更容易学习。
对于有经验的程序员来说,Go 与 Java 的优势
其实对于有经验的程序员来说,很难找到不懂Java的,就当前的各大厂商来看,国内的一线厂商都逐渐向Go靠拢,Google、Facebook、BAT、字节、小米、京东等对Go工程师的需求都很高,如果你是后台开发有机会建议深入的学习一下,就像我们公司招不来Go开发都是招Java开发来写Go的。。。
结论: 学
最后
终于到最后了,写完这篇文章已经是凌晨12:29了,感谢各位能看到最后,希望以上的对比能给你带来一点帮助,写这么多也不容易,感谢大家看到这里,有什么意见或者建议可以留言一起讨论,看到后第一时间回复,也希望大家能给个赞,你的赞就是我写文章的动力,再次感谢。
以上是作为一个多年Java开发用了1年多Go语言的一点感受,本文的评价仅代表我自己,再次感谢。