The Go Programming Language“Go是一种开源的程序设计语言,它意在使得人们能够方便地构建简单、可靠、高效的软件。”(来自Go官网golang.org)Go在2007年9月形成构想,并于2009年11月发布,其发明人是Robert Griesemer、Rob Pike和Ken Thompson,这几位都任职于Google。该语言及其配套工具集使得编译和执行既富有表达力又高效,而且使得程序员能够轻松写出可靠、健壮的程序。
Go和C从表面上看起来相似,而且和C一样,它也是专业程序员使用的一种工具,兼有事半功倍之效。但是Go远不止是C的一种升级版本。基于多种其他语言,它取其精华,去其糟粕。它实现并发功能的设施是全新的、高效的,实现数据抽象和面向对象的途径是极其灵活的。它还实现了自动化的内存管理,或称为垃圾回收。
Go特别适用于构建基础设施类软件(如网络服务器),以及程序员使用的工具和系统等。但它的的确确是一种通用语言,而且在诸多领域(如图像处理、移动应用和机器学习)中都能发现它的身影。它在很多场合下用于替换无类型的脚本语言,这是由于它兼顾了表达力和安全性:Go程序通常比动态语言程序运行速度要快,由于意料之外的类型错误而导致崩溃的情形更是少得多。
Go是个开源项目,所以其编译器、库和工具的源代码是人人皆可免费取得的。来自全世界的社区都在积极地向这个项目贡献代码。Go的运行环境包括类UNIX系统——Linux、FreeBSD、OpenBSD和Mac OS X,还有Plan 9和Microsoft Windows。只要在其中一个环境中写了一个程序,那么基本上不加修改它就可以运行在其他环境中。
本书旨在帮助读者立刻开始使用Go,以及熟练掌握这门语言,并充分地利用Go的语言特性和标准库来撰写清晰的、符合习惯用法的、高效的程序。
Go的起源和生物学物种一样,成功的语言会繁衍后代,这些后代语言会从它们的祖先那里汲取各种优点;有时候,语言间的“混血”会产生异常强大的力量;在一些罕见情况下,某个重大的语言特性也可能凭空出现而并无先例。通过考察语言间的影响,我们可以学得不少知识,比如语言为什么会变成这个样子,以及它适合用于哪些环境,等等。
下图展示了更早出现的程序设计语言对Go产生的最重要影响。
Go有时会称为“类C语言”或“21世纪的C”。从C中,Go继承了表达式语法、控制流语句、基本数据类型、按值调用的形参传递和指针,但比这些更重要的是,继承了C所强调的要点:程序要编译成高效的机器码,并自然地与所处的操作系统提供的抽象机制相配合。
可是,Go的家谱中还有其他祖先。产生主要影响的是由Niklaus Wirth设计的、以Pascal为发端的一个语言支流。Modula-2启发了包概念。Oberon消除了模块接口文件和模块实现文件之间的差异。Oberon-2影响了包、导入和声明的语法,并提供了方法声明的语法。
Go的另一支世系祖先——它使得Go相对于当下的程序设计语言显得卓然不群,是在贝尔实验室开发的一系列名不见经传的研究用语言。这些语言都受到了通信顺序进程(Communicating Sequential Process,CSP)的启发,CSP由Tony Hoare于1978年在发表的关于并发性基础的开创性论文中提出。在CSP中,程序就是一组无共享状态进程的并行组合,进程间的通信和同步采用通道完成。不过,Hoare提出的CSP是一种形式语言,仅用于描述并发性的基本概念,并不是一种用来撰写可执行程序的程序设计语言。
Rob Pike等人开始动手做一些实验,尝试把CSP实现为真正的语言。第一种这样的语言称为Squeak(“和鼠类沟通的语言”),它是一种用于处理鼠标和键盘事件的语言,其中具有静态创建的通道。紧接着它的是Newsqueak,它具有类C的语句和表达式语法,以及类Pascal的类型记法。它是一种纯粹的函数式语言,具有垃圾回收功能,同样也以管理键盘、鼠标和窗口事件为目标。通道变成了“一等”值(first-class value),它可以动态创建并用变量存储。
Plan 9操作系统将这些思想都纳入一种称为Alef的语言中。Alef尝试将Newsqueak改造成一种可用的系统级程序设计语言,但垃圾回收功能的缺失使得它在处理并发性时捉襟见肘。
Go中的其他结构也会不时显示出某些并非来自祖先的基因。例如,iota多多少少有点APL的影子,而嵌套函数的词法作用域则来自Scheme(以及由之而来的大部分语言)。在Go语言中,也可以发现全新的变异。Go中新颖的slice不仅为动态数组提供了高效的随机访问功能,还允许旧式链表的复杂共享机制。另外,defer语句也是Go中新引入的。
Go项目所有的程序设计语言都反映了其发明者的程序设计哲理,其中相当大的一部分是对于此前语言已知缺点的应对措施。Go这个项目也诞生于挫败感,这种挫败感来源于Google的若干复杂性激增的软件系统。(而且这个问题绝非Google所独有的。)“复杂性是以乘积方式增长的。”Rob Pike如是说。为了修复某个问题,一点点地将系统的某个部分变得更加复杂,这不可避免地也给其他部分增加了复杂性。在不断要求增加系统功能、选项和配置,以及快速发布的压力之下,简单性往往被忽视了(尽管长期来看,简单性才是好软件的不二法门)。
Go和C从表面上看起来相似,而且和C一样,它也是专业程序员使用的一种工具,兼有事半功倍之效。但是Go远不止是C的一种升级版本。基于多种其他语言,它取其精华,去其糟粕。它实现并发功能的设施是全新的、高效的,实现数据抽象和面向对象的途径是极其灵活的。它还实现了自动化的内存管理,或称为垃圾回收。
Go特别适用于构建基础设施类软件(如网络服务器),以及程序员使用的工具和系统等。但它的的确确是一种通用语言,而且在诸多领域(如图像处理、移动应用和机器学习)中都能发现它的身影。它在很多场合下用于替换无类型的脚本语言,这是由于它兼顾了表达力和安全性:Go程序通常比动态语言程序运行速度要快,由于意料之外的类型错误而导致崩溃的情形更是少得多。
Go是个开源项目,所以其编译器、库和工具的源代码是人人皆可免费取得的。来自全世界的社区都在积极地向这个项目贡献代码。Go的运行环境包括类UNIX系统——Linux、FreeBSD、OpenBSD和Mac OS X,还有Plan 9和Microsoft Windows。只要在其中一个环境中写了一个程序,那么基本上不加修改它就可以运行在其他环境中。
本书旨在帮助读者立刻开始使用Go,以及熟练掌握这门语言,并充分地利用Go的语言特性和标准库来撰写清晰的、符合习惯用法的、高效的程序。
Go的起源和生物学物种一样,成功的语言会繁衍后代,这些后代语言会从它们的祖先那里汲取各种优点;有时候,语言间的“混血”会产生异常强大的力量;在一些罕见情况下,某个重大的语言特性也可能凭空出现而并无先例。通过考察语言间的影响,我们可以学得不少知识,比如语言为什么会变成这个样子,以及它适合用于哪些环境,等等。
下图展示了更早出现的程序设计语言对Go产生的最重要影响。
Go有时会称为“类C语言”或“21世纪的C”。从C中,Go继承了表达式语法、控制流语句、基本数据类型、按值调用的形参传递和指针,但比这些更重要的是,继承了C所强调的要点:程序要编译成高效的机器码,并自然地与所处的操作系统提供的抽象机制相配合。
可是,Go的家谱中还有其他祖先。产生主要影响的是由Niklaus Wirth设计的、以Pascal为发端的一个语言支流。Modula-2启发了包概念。Oberon消除了模块接口文件和模块实现文件之间的差异。Oberon-2影响了包、导入和声明的语法,并提供了方法声明的语法。
Go的另一支世系祖先——它使得Go相对于当下的程序设计语言显得卓然不群,是在贝尔实验室开发的一系列名不见经传的研究用语言。这些语言都受到了通信顺序进程(Communicating Sequential Process,CSP)的启发,CSP由Tony Hoare于1978年在发表的关于并发性基础的开创性论文中提出。在CSP中,程序就是一组无共享状态进程的并行组合,进程间的通信和同步采用通道完成。不过,Hoare提出的CSP是一种形式语言,仅用于描述并发性的基本概念,并不是一种用来撰写可执行程序的程序设计语言。
Rob Pike等人开始动手做一些实验,尝试把CSP实现为真正的语言。第一种这样的语言称为Squeak(“和鼠类沟通的语言”),它是一种用于处理鼠标和键盘事件的语言,其中具有静态创建的通道。紧接着它的是Newsqueak,它具有类C的语句和表达式语法,以及类Pascal的类型记法。它是一种纯粹的函数式语言,具有垃圾回收功能,同样也以管理键盘、鼠标和窗口事件为目标。通道变成了“一等”值(first-class value),它可以动态创建并用变量存储。
Plan 9操作系统将这些思想都纳入一种称为Alef的语言中。Alef尝试将Newsqueak改造成一种可用的系统级程序设计语言,但垃圾回收功能的缺失使得它在处理并发性时捉襟见肘。
Go中的其他结构也会不时显示出某些并非来自祖先的基因。例如,iota多多少少有点APL的影子,而嵌套函数的词法作用域则来自Scheme(以及由之而来的大部分语言)。在Go语言中,也可以发现全新的变异。Go中新颖的slice不仅为动态数组提供了高效的随机访问功能,还允许旧式链表的复杂共享机制。另外,defer语句也是Go中新引入的。
Go项目所有的程序设计语言都反映了其发明者的程序设计哲理,其中相当大的一部分是对于此前语言已知缺点的应对措施。Go这个项目也诞生于挫败感,这种挫败感来源于Google的若干复杂性激增的软件系统。(而且这个问题绝非Google所独有的。)“复杂性是以乘积方式增长的。”Rob Pike如是说。为了修复某个问题,一点点地将系统的某个部分变得更加复杂,这不可避免地也给其他部分增加了复杂性。在不断要求增加系统功能、选项和配置,以及快速发布的压力之下,简单性往往被忽视了(尽管长期来看,简单性才是好软件的不二法门)。