1.2 Go语言的主要特点

Go语言是一门编译型计算机语言,性能上接近于C、C++等语言,编程时的便捷程度接近于Java、Python等高级语言,并特别对并发处理、多核CPU负载等问题做了优化。

下面列出了Go语言的一些主要特点。注意,Go语言总体来说是一门优秀的计算机开发语言,起点较高,但同时作为一门年轻的语言,它也不可避免地存在一些不成熟的地方。因此,除优点外,这里也列出了一些Go语言中不成熟或有争议的特性。

• 轻量级但内置丰富标准库

Go语言是一门轻量级的语言,自身的编译器和附带工具相对来说都不算大,编译出来的程序也只带有少量的类似垃圾清理、内存分配、并发管理等基本功能的运行时库。但是,与一些只提供基本核心功能而其他功能依赖第三方提供的语言不同,Go语言由于其初始的目标不同,一开始就提供了比较丰富的标准函数库(包)供开发者选用,以便能够快速支持高性能服务端的高效开发。标准库中几乎涵盖了服务端编程所需的大部分功能,例如数学计算、正则表达式、文件处理、文本编码及加密解密、压缩解压缩、缓冲处理、图像处理、数据库处理、并发与共享处理、HTTP与HTML模板处理、运行时与反射处理等。可以看到,开发者几乎可以不依赖任何第三方程序包,就能够进行大多数项目的开发。

• 免费开源

不可否认,免费开源是很多开发者选用Go语言的重要因素之一。由于Go语言的免费开源特性,很快聚集了大量的志愿者为其添砖加瓦、提出建议、贡献代码。第三方开发的函数包和函数库目前已经非常多,涵盖了很多标准库中没有涉及的方面,或者为标准库中不方便使用的内容提供了更好的选择,例如Go语言中对JSON格式数据的处理并非很完美,网络上就已经有了更好的替代函数包;而对于一些类似自然语言处理、高级科学计算、人工智能运算等特别领域的应用,也有第三方提供了专门的函数库。另外,也有人将Go语言的某个版本进行克隆分支后修改成为一门新的语言,同时加入自己喜欢的一些语言特性。

• 跨平台

Go语言支持主流的Windows、MacOS和Linux系统,编写的代码可以在各个平台上通用,仅需要重新编译即可。Go语言甚至还提供“交叉编译工具”进行跨平台编译,例如可以在Windows平台上直接编译出Linux系统上使用的可执行文件。

• 语法简约而严谨

Go语言的语法设计之初,就针对其他语言中一些烦琐的地方进行了较大程度的改进,力求让开发者“不做不必要的事”。同时,为了规范开发习惯、减少开发者记忆的困扰,又提出“能用简单的方法实现的事情就不要用复杂的方式来实现”的原则,对这些原则的坚持有时候甚至到了比较严苛的程度,例如“能用一种简单方法实现的就不要用多种方法实现”,导致一些在其他语言中比较方便但可能引起理解混淆或滥用的特性被放弃。Go语言对于代码格式和一些编程方式也做了比较严格的规定,例如没有用到的函数包是不允许引用的,否则编译时会报错而不通过;如果定义了变量而没有使用,也会编译不通过。在其他语言中,这几种情况一般只会在编译时提示告警,不会强制,由此可见Go语言设计者对于规范开发习惯的决心。有些开发者一开始对这些严格的要求很不适应,习惯后便能够体会到这些约束带来的代码简洁高效、减少阅读干扰的好处。对于代码内部的文档,Go语言也有较好的机制方便其编写。

• 原生高效的并发处理机制

Go语言内置了高效的并发处理机制,它使用一种类似线程但又有所不同(接近于“协程”)的叫作“goroutine”的机制来处理同时并发的多个事务。很有特色的是,几乎任何用户自己编写的函数都可以直接用“go”关键字来将其转化为一个并发的goroutine来执行,这相对于其他大多数语言建立线程的步骤都要简单得多。并且,goroutine的效率大多数情况下还优于一般的线程。高效的并发处理机制使Go语言在处理大量并发请求的服务器和云计算领域有着先天的优势。

• 独特指针操作、内存管理和自动垃圾回收机制

相较于C、C++等语言中虽然灵活但是很容易引起各种异常问题的指针操作,Go语言采用了一定的限制和区别处理,既保证了可以实现各种对内存的操作,又不易引起指针误操作带来的内存泄漏、非法访问内存地址等问题。同时,Go语言有自己独特的内存垃圾回收机制,让开发者在编程时基本不用顾及内存分配、释放等问题。

• 独具一格的面向对象编程方式

Go语言一定程度上可以说是基于C语言的改进,在面向对象编程方面,并没有采用与C++、Java、C#相同的方法去引入复杂的封装、继承、构造函数、析构函数、多态、重载等传统的面向对象特性,但它也没有完全摒弃面向对象的思维,而是巧妙地采用了“结构类型+关联方法”的轻量级解决方案来实现面向对象编程的能力。注意,虽然在Go语言中并没有明确的“对象”和传统的面向对象编程中的一些概念,但在本书中仍然会采用面向对象编程的一些概念和提法,这并不矛盾,只是因为Go语言解决面向对象编程的方法与其他语言不同,其本质还是支持面向对象编程的。

• 网络功能丰富

Go语言的标准库已经具备了丰富的网络开发功能,开发者甚至可以在几分钟内开发出一个Web服务器,并且它是高度可定制的。对于其他一些网络协议和网络格式的处理也有成熟的函数包来处理。

• 性能优异

由于Go语言是在底层上接近于C语言的编译型语言,在面向对象等高级语言特性方面避免了C++等语言中的复杂性,并且在语言中约束了很多可能带来不必要开销的行为,因此,利用Go语言编写的程序效率很高,在不损失接近于高级语言的编写便利性的情况下,编译出来的可执行程序具有相对较快的运行速度。

• 独特的异常处理机制

Go语言自身内置的异常处理机制与其他主流语言常用的try-catch机制有很大的不同,综合来看可以说各有利弊,初次从其他语言过渡过来的开发者可能会需要一个适应的过程。这方面已经引起了Go语言开发团队的重视,并已提出改进的草案征求意见。

• 新的空接口特性

Go语言的另一重要特性是空接口类型,用interface{}来表示。空接口类型是一个特殊的类型,由于Go语言中实现了某接口中定义的所有方法的类型都属于该接口类型,而空接口类型不包含任何方法,所以理论上任何类型都属于空接口类型。因此空接口类型相当于Java、C#等语言中所有对象的基类,或者C++语言中可用于指向任意数据类型的*void指针。空接口类型的引入带来很多开发上的变化,但也有一些争议,认为应尽量减少使用空接口类型。

• 一些较小的特性

Go语言还支持函数多返回值;支持函数作为参数传递;支持匿名函数和闭包;支持反射;支持通过Cgo方式直接调用C语言函数库等。

• 针对图形界面编程功能较弱

Go语言在设计之初就是以服务端开发为主的,主要关注点在结构合理、性能高效、网络和并发处理开发快速等方面,而对图形界面的支持从来就没有放在较高的优先级上。因此,到目前为止,Go语言的图形界面开发并没有在标准库中得到充分体现,而主要是对命令行界面的开发支持较好。当然,由于Go语言本身的各种优点,很多开发者也很希望用它来进行图形界面开发,因此也出现了一些使用Go语言的第三方图形界面开发包,本书中也将介绍一些可行的基于Go语言的图形界面开发方法。

• 一些特殊的限制或不便之处

Go语言也有一些引起不少开发者争议的限制或者功能,这些问题有一些已经得到重视并在尝试做改进,但也有一些是设计者有特殊的考虑,但是没有充分考虑到给使用者提供一定程度的便利性,以及与其他语言开发的系统之间交互的便利性。例如,Go语言中强制要求对外提供的变量和函数方法均必须是大写字母开头(仅在模块内部使用的除外),在Go语言标准库中的JSON语言解析中也要求所有字段使用大写字母开头,否则将默认不被解析。这在与其他系统发送的JSON数据互通时显然会带来问题,因为其他语言中没有这个限制。虽然Go语言中有一定的方法来解决这个问题,但比较烦琐,违背了JSON格式本身就是为了快速处理数据的初衷。因此,网上已经有了一些功能更完整丰富的第三方包来处理JSON。本书后面还将随着章节进展介绍Go语言中一些引起争议的特性。