Golang学习笔记(四):Go原始设计思想及核心特性

本文深入探讨Go语言的设计背景,由Ken Thompson、Rob Pike等大师级人物领衔的豪华设计团队,及其简化自C和C++的独特功能。文章强调Go语言的并发编程、面向接口编程、函数多返回值等八大核心特性,以及其跨平台和交叉编译能力。

1 概述

本人学习Golang的方式和一般人不同,采用了先从大处着手,先从大的方面把握Go编程的总体框架和风格,因此首先就有了前面的三篇文章:

通过上面三篇文章,同时你又有C、C++基础,那么恭喜你!你应该可以开始实战编程了!当然,在编程的过程中你可能还需要不断的问问度娘。

本篇文章还是力图从大处着手,通过对Go设计团队介绍、Go设计团队人员的一些演讲摘要以及总结一些核心特性让你对Go有个更宏观的认识。

2 Go语言设计团队堪称豪华

2.1 Ken Thompson

1943年出生于美国新奥尔良,1966年加入了贝尔实验室,不久独自设计了B语言,并用B语言开发了Unix操作系统的第一个版本,1971年与丹尼斯·里奇共同发明了C语言,并在1973年两人共同用C语言重写了UNIX,1983年图灵奖得主。2006年进入谷歌,2007年和Rob Pike、Robert Griesemer三人一起设计出了Go语言。

在2011年的一次采访中,Ken幽默地谈到设计Go语言的初衷是他们很不喜欢C++,因为C++中充满了大量的垃圾特性。

2.2 Rob Pike

早年在贝尔实验室和Ken Thompson结对编程,公开场合表示Ken是他的导师,也是Unix的先驱,是贝尔实验室最早和Ken Thompson以及 Dennis M. Ritche 开发Unix的猛人,和Ken Thompson一起发明了UTF-8。Go设计团队第一任Leader。

如今虽然和Ken一样已退休并被谷歌尊养起来了,但Rob Pike仍旧活跃在各个Go论坛组中,适当地发表自己的意见。后面会引用他2012年在旧金山给Go SF的演讲稿的部分内容让我们对Go的原始设计思想有个大的了解。

顺便说一句,Go语言的地鼠吉祥物是由Rob Pike的媳妇Renee French设计的。

2.3 Robert Griesemer

Robert Griesemer是Go编程语言的最初三名设计者之一。在此之前,Robert致力于Google V8 JavaScript引擎的代码生成、特定领域语言Sawzall、Java热点虚拟机和Strongtalk系统的设计和实现。他曾经为Cray Y-MP编写了一个矢量编译器,并为APL编写了一个解释器。

目前主要维护Go白皮书和代码解析器等。

2.4 Russ Cox

Russ Cox毕业于麻省理工和哈佛大学,曾在贝尔实验室参与过Plan 9 和 Unix操作系统的开发。在Go开始设计不久,Russ Cox 和Ian Lance Taylor 也加入了 Go 语言的设计团队,由三人团队变成了5人团队。他们 5 人一起开发了两款编译器和一个标准库,为 2009 年 11 月 10 日 Go 语言以开源方式发布打下了基础。

Russ Cox为目前Go团队的leader,他非常年轻,代码提交量排第一。目前很多拿不定主意的决策都是Russ Cox最后拍板。

2.5 Ian Lance Taylor

在GCC的世界中,没有人比Ian更火。在GCC maillist中,Ian的身影呈现在前端中端和后端中,粗略估计1/3的帖子他都给出有价值的回复,绝对不是灌水。

Google推出了go编程语言,Ian基于语言规范独立完成了GCC前端。他写了Gold连接器(比binutils快),最早的GCC MIPSR4000后端,是GCC过程间优化LTO的主要设计者之一,为PostgreSQL数据库增加功能。他曾经是Zembu公司的创始人,目前在Google工作。gccgo编译器的作者和cgo工具链维护者。活跃于各个go订阅组,耐心解答各种问题。

2.6 Brad Fitzpatrick

Brad Fitzpatrick是 LiveJournal.com 的创始人,还是 memcached 等诸多自由软件项目的作者,2007 年选择加入 Google,OpenID、PubSubHubbub 等项目均有他的贡献。2011年在为 Android 项目效力一年半多后,正式成为 Go 语言项目的全职“地鼠”(gopher),目前是net/http标准库包的主要维护者。

当然,Go团队还有很多牛人,就不一一去人肉了 😃

3 Go语言之父Rob Pike说过……

下面通过对Google首席工程师、Go语言之父Rob Pike在旧金山给Go SF的演讲稿摘要,让我们一睹Go语言最初的设计思想:

  • 以C语言为原型,修补部分明显的缺陷,去掉垃圾功能,添加一些缺失的功能。
  • 我们也加入了一下C和C++里没有的东西,比如slice和map、复合文本(composite literal)、顶层文件表达式(这是一个大问题,但经常被忽视)、反射(reflection)、垃圾回收等等,我们还非常自然地加入了并发性。
  • 命名为“Go”,好处有很多,这名字非常简短,容易拼写。工具可以叫做:goc、gol、goa。如果有可交互的调试器/解释器也可以简单地叫它“Go”,后缀名用 .go。
  • 定义空接口语法:interface{}。所有接口都通过这个实现,因此可以用它代替void*。
  • 从C++和Java转向Go的程序员很怀念使用类(class)编程的方式,特别是继承和子类这样的概念。也许关于“class”我只是一个门外汉,但我真没发现模板有什么好处。真正重要的是这些类能为你做什么而不是它们之间是什么关系!
  • 如果说C++和Java是关于类的层次和分类,那么Go的核心思想就是组合(composition)。
  • Go有一个非常不同寻常但是很简单的类型组成方式:嵌入。这些组合技术正是Go的独特之处,与C++或者Java程序截然不同。
  • 在Go语言的首次启航中,我得到了一个“我不能在没有泛型的环境下工作”的反馈,这真是一个奇怪的言论。(作者注:Go 2中有在考虑泛型)

4 Go从C和C++简化的功能

以下也是从Rob Pike在旧金山给Go SF的演讲稿中摘出来的,有些地方不是很懂,但可以看出Go和C、C++大概的区别,我下一步计划好好整理一下Go和C的区别,计划在下一章节写出。

以下是Go从C和C++简化的功能:

  • 规范的语法(不需要符号表来解析)
  • 垃圾回收(独有)
  • 无头文件
  • 明确的依赖
  • 无循环依赖
  • 常量只能是数字
  • int和int32是两种类型
  • 字母大小写设置可见性(作者注:包中首字母大写的全局变量和方法可被其他包调用)
  • 任何类型(type)都有方法(不是class)
  • 没有子类型继承(不是子类)
  • 包级别初始化以及明确的初始化顺序
  • 文件被编译到一个包里
  • 包级全局变量可按任意顺序展示(package-level globals presented in any order—暂时搞不明白什么意思
  • 没有数值类型转换(常量起辅助作用)(作者注:golang 类型转换只能显性转换 不能自动转换)
  • 接口隐式实现(没有“implement”声明)
  • 嵌入(不会提升到超类)
  • 方法按照函数声明(没有特别的位置要求)
  • 方法即函数
  • 接口只有方法(没有数据)
  • 方法通过名字匹配(而非类型)
  • 没有构造函数和析构函数
  • i++是语句,不是表达式
  • 没有++i
  • 赋值不是表达式
  • 明确赋值和函数调用中的计算顺序(没有“sequence point”)
  • 没有指针运算(作者注:Go 有指针,但是没有指针运算,你不能用指针变量遍历字符串的各个字节)
  • 内存一直以零值初始化
  • 局部变量取值合法
  • 方法中没有“this”
  • 分段的堆栈
  • 没有静态和其它类型的注释 (这里不是很懂
  • 没有模板
  • 没有异常(作者注:内置error类型,没有try…catch…)
  • 内建string、slice和map
  • 数组边界检查

5 Go语言的核心特性

Go是一种编译型,并发型,并具有垃圾回收功能的编程语言。Go语言的语法接近C语言。与C++相比,Go语言并不包括如继承、泛型、断言、虚函数等功能,但增加了slice型、并发、管道、垃圾回收、接口(interface)等特性的语言级支持。当然,Go 对于泛型的态度还是开放的,有说法在Go 2中可能支持,目前Go语言对泛型有其替代方案:interface{},一般叫空接口,空接口内部没有声明任何方法,因此指代Go中的任何类型,但声明为空接口类型时,指代接收任何数据类型,在使用通过空接口传递的数据时,通过类型断言的方式接收数据并做进一步处理。这种做法把运行时出错的可能性提前到编译时发现,如有运行时错误也能等到友好的处理。

Go语音的特性很多,我阅读众多博文之后总结了以下几个是最重要的核心特性。

5.1 并发编程

在当今这个互联网时代,并发编程的意义不言而喻。当然,很多语言都支持多线程、多进程编程,但遗憾的是,实现和控制起来并不是那么令人感觉轻松和愉悦。Golang不同的是,语言级别支持协程(goroutine)并发(协程又称微线程,比线程更轻量、开销更小,性能更高),操作起来非常简单,语言级别提供关键字(go)用于启动协程,并且在同一台机器上可以启动成千上万个协程。协程经常被理解为轻量级线程,一个线程可以包含多个协程,共享堆不共享栈。协程间一般由应用程序显式实现调度,上下文切换无需下到内核层,高效不少。

Go语言在并发编程方面非常简洁,只需在调用的方法前(非赋值情况下)或代码块前,加上“go”关键字即可启动一个协程,如下:

package main

import (
    "fmt"
    "time"
)

func testGoroutine(pausems int) {
   
   
    for i := 1; i <= 10; i++ {
   
   
        time.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值