为什么说 Go 是一门简洁高效的语言

01 Go 的诞生

我们都知道 Go语言 是由 Google 公司设计的,准确来说是 2007 年底构思的。

当前的一些主流编程语言(C++、Java、Python等)在解决由 多核处理器,系统的网格化、大规模计算机集群 和 Web编程模型 带来的问题采用的方法大多是 通过迂回的方式而不是正面解决。

也就是治标不治本。

而且,计算机技术发展这么到现在,很多项目的规模都上去了,数百万行的代码量,由成百上千的程序员协同开发,而且每天都进行更新。

就算使用大型编译集群,也可能需要数十分钟甚至数小时来进行一次编译。

Go 就是为了提高这种环境下的工作效率而设计的。

02 认识 Go语言

Go 是一门支持 并发编程 和 内存垃圾回收 的 编译型静态类型 语言,由 Google 开源。

Go 是为了解决开发过程中遇到的问题而设计的,它可能在研究领域没有突破性的进展,但是对大型项目的开发来说是一个绝佳的工具。

它需要解决的问题包括但不限于:编译慢、失控的依赖关系、每个程序员使用同一语言的不同语言子集、程序难以理解(代码难以阅读,文档不全等)、重复劳动、更新代价大、版本偏差、难以编写自动化工具、跨语言构建问题等。

Go语言 从软件工程的大局观出发,避免了许多生产实践中会出现的问题。

比如通过类似于 SWING 调用的方式,将一段 python 代码嵌入到另一种语言,由于改变了 python 代码的缩进格式,从而导致了问题。

所以 Go 采用花括号表示语句块。

03 Go语言特性

3.1 C/C++ 的依赖处理

C 和 C++ 处理包依赖的时候会使用 #ifndef & #endif 来处理重复的 include,这样编译是没有错误的。

但就算是第二次扫描到这个头文件不会重复包含,扫描的耗时还是存在的,会影响编译速度。

后来的 Plan 9 禁止头文件使用 #include,转而在顶层的 C文件 中包含所有的头文件。

这种方式的编译速度比以前快了很多,但原来那种方式仍被广为接受。

3.2 Go 的依赖处理

Go 的依赖引入使用 import 的方式,如 import "fmt"

在编译阶段,语言会将未被使用的依赖视为错误,从而无法编译!

这保证了 Go程序 的依赖关系是明确的,没有任何多余的边际,且减少无用代码。

另一方面,体现对深入依赖的处理。

例如 A、B、C 三个包,A 包引用 B 包,B 包引用 C 包。

要编译这个程序,首先 C 被编译,即被依赖的包必须在依赖于它们的包之前被编译。

然后是 B 包被编译,最后 A 包被编译,然后程序将被连接。

当 A 包编译完成之后,编译器将读取 B 包的目标文件,而不是源码。此目标文件包含编译器处理器处理 A 包代码中 import "B" 语句所需的所有类型信息。这些信息也包含着 B 包在编译时所需的 C 包的信息。

也就是说,当 B 包被编译时,生成的目标文件包含了所有 B 包公共接口所需的全部依赖的类型信息。

为了使编译更加高效,目标文件以导出数据作为它的首要步骤,这样编译器一旦到达文件的末尾就可以停止读取。而导出的数据也放在目标文件中,从而避免需要重新读取数据文件。

Go 的依赖图还有一个重要的特性,就是不包含循环依赖。Go 的编译器和链接器都会对此进行检查以确保不存在循环依赖。

循环依赖要求编译器同时处理大量源文件,从而减慢增量式编译的速度。而且经验告诉我们,循环依赖会带来大片纠缠不清的源码树,最终难以独立管理。

不能使用循环依赖,这迫使我们对 package 的划分提出了更高的要求。

3.3 包

每个 Go 的代码文件,例如 “encoding/json/json.go”,都以包声明开始。

// 包声明  json.go
package json
/

// 引入包  main.go
import "encoding/json"

标准资源库以外,通常约定以项目或公司名作为命名控件的根,如 import "google/base/go/log"

此外,Go 还可以识别网站资源的 URL 来引用远程仓库(go get xxx),比如 GitHub 的资源。

go get 命令递归下载依赖,此特性得以实现的原因是依赖关系的明确性。另外,由于引入路径的命名空间依赖于 URL,使得 Go 相较于其他语言,在包命名上更加分散和易于扩展。

3.4 语法

和 C语言 家族的其他几个成员相比,Go语言的词法更为精炼,仅 25 个关键字。

Go语言的词法也更加规范,易于解析。

关于 Go语言是省流助手,可以点击 这里 查看。

3.5 并发

Go语言实现了两种并发形式,一种通过多线程共享内存,就是 C++ 和 Java 等语言中的多线程开发;另一种是Go语言独有的,也是Go语言推荐的 CSP(communicating sequential processes)并发模型。

Go语言仅实现了 CSP 中 process 和 channel 这两个概念。

process 就是Go语言中的 goroutine,每个 goroutine 之间是通过 channel 通讯来实现数据共享。

不要通过共享内存来通信,要通过通信来共享内存。

3.6 垃圾回收

Go语言没有显式的内存释放操作,那些被分配的内存只能通过垃圾回收器唯一途径来返回内存池。

虽然 Go 是一种支持垃圾回收的编程语言,但是资深程序员能够限制施加给回收器的压力从而提高程序的运行效率。

Go的安装包中提供了一些非常好的工具,用于研究程序运行过程中动态内存的性能。

04 总结

软件工程指导下的 Go语言 的设计,同大多数通用型的编程语言相比,Go语言更多是为了解决我们在构建大型服务器软件过程中所遇到的问题而设计的。

在设计过程中,GO语言着重于清晰和简洁,以及较高的可组合性最后得到的是一门使用起来效率高而且很有趣的语言,且有着极强的表达能力和强大的功能。

造成这样结果包括但不限于:清晰的依赖关系、清晰的语法、清晰的语义、偏向组合而不是继承、编程模型(垃圾回收、并发)所代理的简单性、易于为它编写工具(gotool、gofmt、godoc、gofix等)

资料参考:https://talks.golang.org/2012/splash.article

猜你喜欢

转载自blog.csdn.net/weixin_44778151/article/details/121803457