Go
- 1. 系统编程语言明日之星—骋辞
■ 文 / 余锋
G
o 语言由Google 提供支持,于2007 年 了动态语 言的弹性 , 又有了静态语言的安全性
9 月开始浮出水面 , 出自 Rob Pike、 和高性能 。Rob Pike 指出 Go 代码的编译基本
Ken Thomason 等大师之手 , 是一种 上可以达到 C 语言的速度 , 几乎可以在瞬间完
支持并发和垃圾回收的编译型编程语言。 成 。 而在运行效率上已经和 C 语言很接近 , 同
Go 语言是基于 BSD 许可发行的开源项目 , 时支持多核心并发运算 。 来自语言性能比较网
目前只支持Linux、Mac OS X和Windows平台。 站 Computer Language Benchmarks Game
由于团队资源及社区规模的限制 , 目前 Go 还无 的数据也验证了这一点 。 目前这个 Go 社区非常
法支持更多的操作系统,因此需要更多的参与者 活跃 , 新的特性和包在不断地被提出和加入 ,
来进行移植。 加上有 Google 在背后强力支持和推广 , 个人认
作者介绍: Go 语言创建伊始 , 就目标明确 —— 创建一 为应用前景非常广阔 。
Cover Story
余锋,就职于淘宝核心系 种高性能 、 开发迅速 、 安全且富有趣味的系统
统研发部。多年C和网络
开发经验,专注于高性 编程语言 。 各种高性能的网络服务器 、 文件存 Go能解决什么问题呢?
能、容错、分布式服务器
储系统 、 数据库等 , 都非常适合使用 Go 进行开 我们在编写系统程序时总是会面临以下挑
的研究和实现。
发 。 当然 Go 也可以运用在其他领域 ,Go 的官 战 : 第一 , 硬件发展得很快 , 软件技术总是突
方网站 golang.org 就是使用 gdoc 实现的 。 破得很慢 ; 第二 , 复杂的系统依赖性很强 , 平
Go 已经在 Google 公司内部尝试使用 , 但 台 、 库 、 管理这些依赖相当麻烦 ; 第三 , 目前
封面报道
是并没有大规模地部署,因此仍处于试验阶 可用的系统语言如 C++、Java 太笨拙 , 也太复
段 , 需要丰富的测试和考验 。 杂 , 在处理复杂情况时感觉力不从心 ; 第四 ,
Go已经给了我们一个华丽的亮相,在工 复杂的内存管理和资源管理 ; 第五 , 多核心机
程层面,Go语言官方目前还没有自己的编辑 器的涌现 , 在未来几年里面 128 核心的机器应
器 , 但是发布包带了 Emacs、VI 以及 Xcode 该会很常见 , 我们难道还是用最原始的线程 机
的插件 , 方便用户的编辑 。 它目前有 2 个编译 制和同步原语来面对 ?
器 : 源于 Plan9 的 Native 8/6g 编译器和以 GCC 大部分系统语言并不是设计来解决这些问
为后端的 Gccgo。 Gccgo 能编译出来更高效的 题的,而且新涌现的大多数程序库也并没有
代码 , 还可以和其他的 gcc 库相链接 。 但是遗 改善这些问题 , 相反加剧了复杂度 。 正如 Rob
憾的是 Gccgo 尚未实现垃圾收集 ,Goroutine Pike 说 :“ 我们开发 Go, 是因为近 10 年来开
通过 pthread 实现 , 调度开销大且栈空间占用 发系统程序之难让我们有点沮丧 。 这时候 Go
多 , 而且编译时间较长 , 无法在实际项目中使 来拯救我们啦 !”
用 。 排错器和调优器目前还不大可用 。
我看好 Go 的原因是 , 这个语言不是凭空或 设计目标
者实验室设计的 , 而是填补过去 10 年在系统编 系统编程语言
程软件方面的不足 。 作为系统软件的编写者 , 快速编译和执行
经常会深深地感到目前常见系统语言在面对大 类型安全性和内存使用安全
规模网络应用的力不从心 , 在不断涌现的多核 很好的支持并发计算
心硬件前的无奈 , 在多线程和各种锁中间的痛 高效低延迟的垃圾回收算法
苦 , 在不停地制造各种各样的轮子的困惑 , 以
及在使用很原始的排错器的低效 。Go 拥有的这 设计原则
些现代特性都是系统用户梦寐以求的 , 既结合 更少的关键词 , 减少无谓的输入
64 程序员
- 2. 保持概念正交 息 , 有同步和异步之分 。Channel 在生产者和消费者之间
保持简单 架设起沟通的桥梁 , 承担起传统语言消息队列的作用 。
减少类型 , 无类型层次 , 避免罗嗦 Goroutine:Goroutine 是使并发编程变得容易的核
心 。 实现上是通过系统的线程来多路派遣协程 , 使得函数
语言特性 的执行看起来独立 。 当一个协程阻塞的时候 , 比如说费时
G o 语 言 脱胎 于 C 语 言 , 同 时 还 从社 区 的 其 他语 言如 的系统调用 , 调度器就会自动把其他协程安排到另外的线
Pascal、 CSP、Occam 借鉴了很多特性 , 添加了如包管 程去执行 , 从而保证了系统的不间断运行 。 这个调度对于
理、反射、 垃圾回收器、动态类型、并发以及并行机制等。 程序员是透明的 , 从用户的角度来看 , 协程在一直运行 。
它有一些有趣的特性 : 而且这个调度的开销非常小 , 典型的 CPU 每秒钟可以调度
融合多种语言的特性 , 各个社区的人都感觉会很熟 百万次 , 协程还支持堆栈的自增 。 这两个设计使得我们可
悉 , 特别是 C、Lua、Python 社区的用户非常容易上手 。 以创建大量的 goroutine, 模拟现实世界对象的行为 , 大
支持面向对象编程 , 但是不支持层次继承 。 大简化了程序的设计和实现 。
清晰 、 精确的语法 。 Network 支持 : 目前支持 Tcp/Udp 协议 , 有统一的编
大写符号导出公共符号 , 小写是私有的 。 程接口 , 方便未来支持更多的协议 , 通过内核 POLL 支持
函数或者块开始注释是文档 , 方便 gdoc 生成文档 。 成千上万的并发连接 。 在网络读写暂时无效的时候 , 网络
改进的 If、Case 复合语句 , 允许在条件判定前 , 执 模块会自动把该句柄注册到系统的 poll set, 并且让出执行
行初始语句 。Case 不支持自动 fall through, 支持多个判 权 , 等待读写事件的发生 。 一旦读写事件得到通知 , 网络 互
断条件和表达式 。 模块内部通过 Channel 通知刚才被阻塞的操作继续执行 。
联
网
轻量的类型系统 , 强类型 , 没有隐式的转换 , 显式 从用户使用角度来看 , 网络的读写都是顺序执行的 , 极大 产
类型转化 。 地简化了编程 。 品
指针运算由 slice 代替 , 提高安全性的同时也有很高 正是 Network+ 闭包 +Goroutine+Channel 让 Go 语言 设
计
的效率 。 这么突出 , 突破了用户在编写大规模系统程序时的局限 。
内置基本数据类型数组和字典 。 10
年
type: 相当灵活的 struct, 支持匿名字段 , 复用看起 库实现
来很优雅 。 完全用 Go 语言实现 , 不依赖其他系统库 。
灵活但独特的 interface: 接口类型 , 接口实现分 模块管理 。 一个 Package 可以分散在多个文件里 ,
离 。 若一个 struct 实现了 interface 声明的方法则视为实现 通过包名整合在一起 。 支持包层面的初始化操作 。
此 interface。 通用类型 interface{} 用来表示同样类型 , 用 接口库如 XML、Asn1、JSON、IO 库 、 压缩 、 加密
于实现包容器和用于参数省略的场合 。 库等 , 比较齐全 , 极大地方便了用户 。
range:for语句支持通用的迭代,支持数组、字 支持 Unicode。
典 、 通讯管道 。 特别是通讯管道结合 Goroutine, 由生产
者负责在一端输入数据 ,range 充当消费者 , 从另外一端 与其他语言的交互
消费数据 。 Cgo 支持 C 和 Go 语言编程混合 , 使得 Go 语言的扩展
reflection: 用于实现多参数机制和实现比如 XML、 非常容易 , 让 Cgo 来做参数和类型转换 , 直接连接用户的
JSON 库 , 很直观地把结构的字段名和值映射起来 , 但是 C 函数 。
执行效率不高 。
defer 负责资源的自动释放 , 有效地避免资源泄漏 。 目前存在的问题
语言的面世时间比较短 , 实现和社区都不够成熟 ,
语言亮点 一些关键的语言特性如 select timeout 还没有实现 , 编译
闭包 : 函数是第一类对象 。 有了闭包 , 我们很容易把 器也不大完善 。
数据和函数结合在一起 , 形成一个独立的执行体 , 无需关 语言库少 , 主要体现在缺少高级网络 、GUI、 数据
心数据的泄漏 , 是并发编程的基础 。 库访和媒体处理库 。
Channel:CSP 的核心思想是通过消息共享 , 而不 基于 Go 的应用还比较少 , 甚至在 Google 内部也还
是内存共享 。 而消息共享机制就是通过 Channel 来传递消 是个试验项目 , 还没有大规模的应用 。
2010 08 65