『GCTT 出品』Go 语言之美

最近,我在做兴趣项目的时候开始探索 语言,被 语言的美征服了。

语言的美在于它在灵活使用(常见于一些动态,解释型语言)和安全性能(常见于一些静态,编译语言)之间有一个很好的平衡。

除此之外,还有另外的两个功能让我觉得 语言非常适合现代的软件开发。我会在之下优势的部分阐述。

其中之一是 对语言并发性的一流支持(通过 ,和 实现,下面解释)。 并发,通过其设计,使您能够有效地使用您的 马力。 即使您的处理器只有1个内核,并发的设计也能让您高效地使用该内核。 这就是为什么您通常可以在单台机器上运行数十万个并发 (轻量级线程)的原因。 和 是分布式系统的核心,因为它们抽象了生产者 - 消费者的消息范例。

我非常喜欢 的另一个特性是接口 () 。 接口为您的系统提供松耦合或分离组件。 这意味着你的代码的一部分可以只依赖于接口类型,并不关心谁实现了接口或接口是如何实现的。 然后,您的控制器可以提供一个满足接口(实现接口中的所有功能)的代码的依赖关系。 这也为单元测试提供了一个非常干净的架构(通过依赖注入)。 现在,您的控制器可以注入代码所需的接口的模拟实现,以便能够测试它是否正确地执行其工作。

综上所诉我认为 是一门很棒的语言。 特别是对于像云系统开发( 服务器,,缓存等),分布式系统,微服务等用例。因此,如果你是一名工程师或初创公司试图决定你想要探索或尝试的语言,请认真的考虑一下 。

在这篇文章中,我将讨论该语言的以下几个方面:

a)介绍

b)为什么需要Go

c)目标受众

d)Go的优势

e)Go的弱点

f)走向2

g)Go的设计理念

h)如何开始

i)谁在使用Go

介绍

是一款开源语言,由 , 和 在 创建。开源代码意味着每个人都可以通过为新功能提供建议,修复错误等来为语言做出贡献。语言的代码在GitHub上。 这里提供了有关如何为语言做出贡献的文档。

为什么需要 Go

作者提到,设计新语言的主要动机是解决 的内部软件工程问题。 他们还提到 实际上是作为 的替代品而开发的。

提到 编程语言的目的:

“因此,Go 的目的不是研究编程语言设计; 它是为了改善设计师和同事的工作环境。 Go 比编程语言研究更关注软件工程。 或者换句话说,就是为软件工程师服务的语言设计。”

困扰Google软件工程视野的问题(摘自(https://talks.golang.org/2012/splash.article)):

a)缓慢的构建 - 构建有时需要一个小时才能完成

b)不受控制的依赖

c)每个程序员使用该语言的不同子集

d)程序理解不佳(代码难以阅读,记录不当等等)

e)重复努力

f)更新的成本

g)版本歪斜

h)编写自动工具的难度

i)跨语言构建

为了成功,Go必须解决这些问题(摘自(https://talks.golang.org/2012/splash.article)):

a)Go必须能大规模的使用,用于多人的大组,并且适用于有大量依赖程序的项目。

b)Go的语法必须是让人熟悉的,大致类C。 谷歌需要在Go中快速提高程序员的效率,这意味着语言的语法的变化不能太激进。

c)Go必须是现代的。 它应该具有像并发这样的功能,以便程序可以高效地使用多核机器。 它应该有内置的网络和Web服务器库,以便它有助于现代化的发展。

目标听众

是一种系统编程语言。 对于诸如云系统(网络服务器,缓存),微服务,分布式系统(由于并发支持)而言, 确实非常出色。

优势

a)静态类型: 是静态类型的。 这意味着您需要在编译时为所有变量和函数参数(以及返回变量)声明类型。 虽然这听起来不方便,但这有一个很大的优势,因为在编译时本身会发现很多错误。 当你的团队规模增加时,这个因素起着非常重要的作用,因为声明的类型使得函数和库更易读,更容易理解。

b)编译速度: 代码编译速度非常快,因此您无需继续等待代码编译。 实际上, 命令会很快启动你的程序,所以你甚至不会觉得你的代码是先编译好的。 这感觉就像一种解释性语言。

c)执行速度: 根据操作系统()和代码正在编译的机器的 指令集体系结构(等), 代码直接编译为机器代码。 所以,它运行速度非常快。

d)便携式: 由于代码直接编译为机器码,因此,二进制文件变得便携。 这里的可移植性意味着你可以从你的机器(比如 )获取二进制文件并直接在你的服务器上运行(如果你的服务器也在 架构上运行 )。

由于 二进制文件是静态链接的,这意味着您的程序需要的任何共享操作系统库都将在编译时包含在二进制文件中。它们在运行程序时不会动态链接。

这对于在数据中心的多台机器上部署程序具有巨大的好处。如果您的数据中心中有 台机器,只要将二进制文件编译为您的机器所运行的相同操作系统和指令集体系结构,就可以简单地将您的程序二进制文件 到所有这些机器。 你不需要关心他们正在运行的 版本。 不需要检查/管理依赖关系。 二进制文件运行的过程中,所有的程序都跑起来了。

e)并发性: 对并发有一流的支持。 并发是 的主要卖点之一。 语言设计师围绕托尼霍尔的论文设计了并发模型。

Go 运行时允许您在机器上运行数十万个并发 。 是一个轻量级的执行线程。 运行时将这些 复用到操作系统线程上。 这意味着多个 可以在单个操作系统线程上同时运行。 运行时有一个调度程序,其任务是调度这些 执行。

这种方法有两个好处:

1:初始化时的 Goroutine 具有 2KB 的堆栈。与一个一般为 1 MB 的 OS 线程堆栈相比,这非常小巧。当你需要同时运行几十万个不同的 goroutine 时,这个数字很重要。如果你要并行运行数千个 OS 线程,RAM 显然将成为瓶颈。

2:Go 可以遵循与 Java 等其他语言相同的模型,它支持与 OS 线程相同的线程概念。但是在这种情况下,OS 线程之间的上下文切换成本比不同的 goroutine 之间的上下文切换成本要大得多。

由于我在本文中多次提及“并发性”,因此我建议您查看 关于“并发性不是并行性”的讨论。在编程中,并发是独立执行的进程的组成,而并行则是(可能相关的)计算的同时执行。除非你有一个拥有多个内核的处理器或者拥有多个处理器,否则你不能真正拥有并行性,因为 内核一次只能执行一件事。在单个核心机器上,只有并发才是幕后工作。 调度程序针对处理器上的不同时间片调度不同的进程(实际上线程,每个进程至少有一个主线程)。因此,在某个时刻,您只能在处理器上运行一个线程(进程)。由于指令的执行速度很快,我们感觉到有很多事情正在运行。但实际上这只是一件事。

并发是一次处理很多事情。并行是一次做很多事情。

f)接口: 接口使松散耦合的系统成为可能。 中的接口类型可以被定义为一组函数。而已。任何实现这些函数的类型都会隐式地实现接口,即不需要指定类型实现接口。这由编译器在编译时自动检查。

这意味着你的代码的一部分可以只依赖于一个接口类型,并不关心谁实现了接口或接口是如何实现的。然后你的主/控制器函数可以提供一个满足接口(实现接口中所有函数)的依赖关系。这也为单元测试提供了一个非常干净的架构(通过依赖注入)。现在,您的测试代码可以注入代码所需的接口的模拟实现,以便能够测试它是否正确地执行其工作。

虽然这对于解耦是非常好的,但另一个好处是您可以开始将您的体系结构视为不同的微服务。即使您的应用程序驻留在单个服务器上(如果您刚刚开始),也可以将应用程序中所需的不同功能设计为不同的微服务,每个微服务都实现它承诺的接口。所以其他服务/控制器只是调用界面中的方法,而不是实际关心它们是如何在幕后实现的。

g)垃圾收集: 与 不同,你不需要记住释放指针或担心 中悬挂指针。垃圾收集器自动完成这项工作。

h)不报错异常,自己处理错误: 我喜欢 没有其他语言具有的标准异常逻辑。去强迫开发人员处理“无法打开文件”等基本错误,而不是让他们将所有代码包装在 块中。这也迫使开发人员考虑需要采取什么措施来处理这些故障情况。

i)惊人的工具:关于的最好方面之一是它的工具。它有如下工具:

i)Gofmt:它会自动格式化和缩进你的代码,这样你的代码看起来就像这个星球上的每个 开发者一样。这对代码可读性有巨大的影响。

ii)Go run:编译你的代码并运行它们,都是:)。因此,即使 需要编译,这个工具也让你觉得它是一种解释型语言,因为它只是编译你的代码的速度非常快,以致于当代码编译完成时你甚至不会感觉到它。

iii)Go get:从 下载库并将其复制到 ,以便您可以将库导入到项目中

iv)Godoc: 解析您的 源代码 - 包括注释 - 并以 或纯文本格式生成其文档。通过 的网络界面,您可以看到与其所记录代码紧密结合的文档。只需点击一下,您就可以从函数的文档导航到其实现。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181112B0HYLE00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励