GoLang,开发人员需要学习的下一门语言
起源故事
据说,GoLang 的诞生正值开发者们等待程序编译完成的空档期。这些开发者们厌倦了等待,厌倦了无所事事。谷歌的三位程序员,一如既往地挺身而出,迎接了这一挑战。Go 于 2009 年发布,1.0 版本于 2012 年发布。谷歌的三位工程师(Robert Griesemer、Ken Thompson 和 Rob Pike)创建了一门系统级语言来取代所有其他语言,因为该领域已经有一段时间没有出现新的语言了,而且现有的语言都没有将多线程作为核心原则。
这三位程序员过去都参与过一些相当重要的项目,包括 C 语言、Unix、UTF-8、JVM 以及其他一些编程语言。Go 是近来第一门让现代工程师能够同时拥有高效编译、高效执行和易编程能力的语言。这三者并非都存在于同一种主流编程语言中。Go 试图将所有这些能力融入一种语言中。
Go 在 Google 做什么?
Go 是一种系统级编程语言,专门用于大型分布式系统和高度可扩展的网络服务器。它旨在根据 Google 的需求取代 C++ 和 Java。Go 旨在缓解大型软件系统开发过程中的一些缓慢和繁琐的问题。更具体地说,Go 有助于解决……
- 编译慢,执行慢
- 使用不同语言子集进行协作的程序员
- 可读性和文档
- 语言一致性
- 版本问题
- 多语言构建
- 依赖关系难以维护
不要轻信我的话
Go 在StackOverflow上排名跃升至第五位,成为最受“喜爱”的语言。开发者调查显示,目前使用 Go 的开发者中,65.6% 表示,如果可以选择,他们将继续使用 Go 而不是其他语言。
Go 也是Github上增长最快的语言之一,其发展速度令人惊叹。2016年,Go 有大约 18.8 万个拉取请求,比上一年增长了 93%。2017年,Go 的拉取请求数量跃升至 28.5 万,成为 Github 上第九大热门语言。
Go 已经成为许多开发者“下一门要学习的语言”。HackerRank的调查结果恰恰表明,Go 遥遥领先。这项评估是在今年 2 月进行的。
显然,Google 的冠名对 Go 的成功和普及起到了至关重要的推动作用。你现在感兴趣了吧?好吧,假设你在决定点击一篇关于 Go 的文章之前没有感兴趣的话……
系统级语言为何如此受欢迎?
简单性或许是 Go 如此容易被接受的一大原因。纵观其他语言及其发展历程,你会发现它们不断引入新功能,这听起来不错,事实也确实如此,别误会我的意思。突出的问题是,这些语言在功能、外观和使用体验上越来越趋同。Go 就是它本身,并没有试图融入太多其他元素。它很好地覆盖了自身的基础,但又不会过度扩张。这完全是有意为之。三位开发人员达成的协议*是,他们三人必须就一项功能达成一致,并且该功能才是Go 应该包含的正确功能。这是为了确保 Go 拥有 Rob、Robert 和 Ken 都认为至关重要的简单性和可读性。目前,Go 的理念是,从长远来看,Go 的功能和外观设计不会有重大变化。开发人员唯一考虑添加的建议功能是泛型。语言常见问题解答文档提到,泛型可能会在未来某个时候添加,但他们只是觉得没有那么紧迫。最终可能会有 Go 2,但可能还要过几年。
为什么如此固执己见?
Go 团队得出的结论是,随着特性和功能的增多,项目复杂性和新开发人员的加入以及学习 Go 语言并开始编写生产级代码的难度都会增加。Go 旨在让任何开发人员几乎在第一天就能开始编写生产级代码。
让我们以 JavaScript 为例,它对大多数开发者来说都比较熟悉(因为它是全球最流行的编程语言)。一个函数的编写方式多种多样,但在 Go 中,该函数几乎只有一种。你不需要费力地设身处地地去理解编写该 JavaScript 函数的开发者,也不需要像几个月前那样去思考自己,就能完全理解眼前的代码。我同意,用 JavaScript 编写代码可能更有趣,但 Go 更易于维护、简洁易用,并且整体开发速度更快。
并发不是并行
需要解释的是,并发并非本质上就是并行。并发是一种处理多个进程的更结构化的方法,而不是同时执行一堆操作(或同一操作的多个实例)。因此,并发并不意味着两个进程永远不会同时运行。这种情况确实会发生,但它更多地关乎所述进程之间的通信。知道何时执行某事以及如何执行。因此,在 Go 中,它们旨在进行通信。虽然你可以创建并行,但这并不是全部。
为了更好地解释这个想法,想象一下(本着世界杯最近落下帷幕的精神)一支正在比赛的足球队。场上的每位球员都是一个单独的进程(在本例中是 GoRoutine)。他们都在奔跑,并以球(数据)作为触发器或通信点进行通信。守门员并非一直在移动,但当球位于自己半场的某个位置时,以及当球靠近禁区时,他会做出相应的动作。每个球员(GoRoutine)都有自己的工作,这些工作彼此独立,但又相互协调。如果我们纯粹讨论并行性,那么每个球员都会独自玩游戏,对其他球员的行为毫不关心。
Go 针对并发的解决方案:
GoRoutines(执行)
Go 编程语言中的 GoRoutine 是由 Go 运行时管理的轻量级线程。如果在函数前面加上“go”,则表示它将与其余代码并发执行。
通道(通信)
通道是连接并发 GoRoutine 的管道。您可以通过通道在 GoRoutine 之间发送值和信号。这允许同步执行。
Select (协调)
Go 中的 Select 语句允许您在一个通道上等待并观察多个操作。将 GoRoutines 与通道结合使用将展现 Go 并发的真正威力。
Go 有何独特之处?
- Go 实现了零延迟的垃圾收集和快速的编译时间。该语言完全(我的意思是完全)抽象了垃圾收集和手动内存管理。如果用 C 和 C++ 等语言手动实现,这两项操作都会耗费大量的时间。
- Go 中实际上没有类。相反,结构体和接口都是有类型的。下面是一个非常简单的示例。
- Go 是静态类型的,因此大多数(如果不是全部)错误都是在编译时而不是运行时捕获的。Go 是类型安全的,这意味着你不能随意修改类型,以免程序崩溃。Go 也是内存安全的,这意味着你不必处理诸如缓冲区溢出和悬垂指针之类的内存漏洞。
- 在许多其他编程语言中,您必须选择抛出/返回异常/错误,但由于 Go 可以返回元组,因此您可以在必要时抛出错误并返回值。这一点很重要,因为 Go 没有异常。Go 依赖于“if”语句来处理错误。您可以自行决定如何处理它。这听起来可能像是一种限制,但在适当的情况下,它可以带来极大的自由和强大的功能。
- 函数可以传入其他函数、返回函数,也可以声明为变量。函数也可以在其他函数内部创建,这也称为闭包。
- Go 有一个defer关键字,允许延迟执行功能。确切地说,这意味着你将某些操作或执行设置为延迟执行,直到其周围的函数返回。延迟调用无论位于何处都会立即执行,但要等到周围的函数完成才会执行。此外,延迟函数调用的执行顺序是后进先出。
GoLang 还有更多独特之处,但这只是对一些很酷的东西的快速回顾。
我的编程语言比你的好
C 和 C++
如前所述,Go 与 C 和 C++ 相比具有一些优势,例如前面提到的类型和内存安全,并且(在我看来,可能任何使用过它们的人都是这么认为)Go 的入门期要容易得多,也快得多。此外,一旦您理解了 Go,阅读 Go 和理解代码的作用就会容易得多。这似乎是一个显而易见的评价……但是有很多人知道 Javascript,但他们并不了解 Javascript。我认为 Go 比 C 最大的优势是(如我之前提到的)如何完全处理垃圾收集和内存管理。有一个包(unsafe),其中包含允许您绕过 Go 的类型安全的操作,并允许您以任何您想要的方式处理内存/指针。我还必须提到,这可能会使您的二进制文件不可移植,并且不受 Go 1.0 兼容性指南的保护。
锈
之所以将 Rust 和 Go 进行比较,是因为它们都是大约同时出现的系统级语言,并且都致力于解决对方无法解决的问题。Rust 的目标是与 C 和 D 完全互操作,而 Go 则不然。
Go可以与这些编译器互操作。Go 有两种编译器实现:gc和gccgo。gc 使用不同的调用约定和链接器,因此只能与遵循相同约定的 C 程序链接。gccgo 是 GCC 的前端,可以与 GCC 编译的 C 或 C++ 程序链接。gccgo 的编译速度比默认的 gc 慢,但支持更强大的优化,因此许多使用它编译的程序运行速度会更快。这需要非常谨慎,甚至需要更多的耐心。
cgo程序提供了外部函数接口机制,允许在 Go 代码中安全地调用 C 库。SWIG 将此功能扩展到 C++ 库。
简单地说,Go 旨在成为一种独立的、可维护的、高效的语言,而 Rust 基本上只是为 C 开发人员提供了一种比 C 更简单、更快速的新编码方式(但事实并非如此)。
Java
Java 和 Go 显然会被拿来比较,但它们之间有着惊人的差异。Java 的应用范围更广,拥有丰富的框架,并且多年来一直主导着行业。既然 Java 有很多理由,我就不多说了,Go 更胜一筹。请记住,Go 并非旨在完全取代 Java,而是在它应该改进的领域进行改进。
-
由于层次结构和多态性,Java 项目变得非常难以维护。Go 和 Java 都支持接口,它们可以做几乎相同的事情,但 Go 的接口更灵活。
-
JVM 从名称上看(显然)是一个虚拟机,Go 编译的二进制文件可以在处理器上本地/直接运行。
-
Java 在标准库中没有实现任何类似于goroutine的功能。虽然有一些库可以解决这个问题,但即便如此,这些库的维护难度仍然相对较高。而 Go 则拥有开箱即用的出色并发能力。
-
一旦开发团队学会了这门语言,Go 的开发周期无疑会更快。
Python 和 Ruby?
一个意想不到的比较是,Go 被视为 Python 和 Ruby 等语言的替代或补充语言。
在需要高性能的领域,Go 已经取代了 Ruby。Go 作为服务器端语言,能够与几乎所有数据库交互,而 Ruby 的兼容性有限,只能使用最流行的数据库。
我读到过很多 Python 程序员决定转向 Go 的案例,YouTube 上有很多相关的讲座、博客文章,以及 Python 和 Go 的代码对比。尽管 Go 不是一种脚本语言,但人们一直在用它编写脚本。
哪种语言被认为是 Go 最强大的竞争对手之一?嗯,实际上是 Node.js,因为 Node 解决了“HTTP 请求的高并发性以及对数据库的大量读写”。GoLang 的表现要好得多。
我建议查看Hackernoon 的文章,其中展示了一个真实的例子,说明了为什么要使用 GoLang 代替 Node.js,并使用两种相应的语言构建 AWS Lambda 函数,然后对它们进行负载测试。
我已经多次谈论过 Go 的优秀之处,但它也有一些缺点。如果你只是按照 Go 的预期用途来使用,那么这些缺点基本上无关紧要,因为它的很多功能并非设计来做。Go 确实能很好地完成它该做的事情。它速度快、易于学习,而且高度可扩展。但是,在一些它显然无法做到的事情上,它确实存在一些明显的局限性,但我必须说,这主要只是开发者的观点。用合适的工具做合适的工作。
缺点:
很少有人关注您“获取”的软件包的版本维护,并且如果您认为未来版本会导致问题,则建议您将所需的版本化软件包存储在本地或包含在您的存储库中。(有解决方案。请参阅dep)
-
没有泛型,没有.map、.reduce、.filter
-
没有例外或断言,如前所述(但我觉得这可能有两种情况)
-
不使用三元运算。使用老套的“if else”语句。
-
绝对不容忍未使用的变量或导入(但这真的是一件坏事吗?)
-
你的病毒防护程序可能会认为你编译的二进制文件已被感染,因为它不理解 Go 二进制文件的结构😅
-
没有指针运算(但这是为了安全,并简化了垃圾收集器的实现)
-
说实话,处理 GOPATH 有点麻烦。你被迫在 GOPATH 中完成所有 Go 项目,但像 VSCode 和 GoLand 这样的 IDE 允许你为项目设置 GoPath,而不会影响系统实际的 GOPATH。
总结
Go 的受欢迎程度正在快速增长,如果你正在涉足无服务器和云领域,我认为学习 Go 至关重要。Go 的编译和执行速度优势至少可以显著提升你的效率和执行成本。它已经成为云基础设施的关键组件,并且很可能在相当长的一段时间内都不会消失。
本文最初发布于 Medium @Slalom-Technology
文章来源:https://dev.to/dizveloper/golang-the-next-language-to-learn-for-developers-pc5