Go语言语法及标准库变化
Go从1.0版本到现在(2015年)已经有三年多的时间,大的版本发布了五个,下面大家一起看看每个大版本分别都改了什么,当然这里不可能把所有的细节都提到,但我认为重要的会提出来。
首先是Go 1.1,Go 1.0于2012年4月发布,此后基本维持了每半年发布一个新版本的时间间隔。Go 1.5比较例外,在Go 1.5的拖累下,Go并没有坚持半年发布一个版本的惯例,因为Go 1.5的变化非常大。大家如果对Go有所了解,就会知道Go 1.5将基础的实现用Go语言重新写了一遍,但之前是用C写的。
Go 1.1是Go 1.0之后比较大的版本,相对于后面几个版本而言,里面有更多的语法变更。例如,它最重要的功能是支持方法值,如有一个Foo类型,假设里面有个写的方法,我直接定义一个p的变量,就是访问了这个函数,等价于一个闭包、并调用 p.Write( ),相当于把第一个参数直接通过p绑定了。有点类似闭包,假设N个变量,少了一个就变成了N-1,第一个参数绑定一个就变成了一个新的闭包。这样的好处是,Go里面大量的函数有上下文,p.Write方式非常适合代入上下文,而且是非常优雅的。
区别于方法表达式(*Foo).Write,结果类型为func(p *Foo, b[]byte)(int, error),方法表达式非常简洁,而且容易理解。
另外,Go 1.1的改进还包括int、uint类型长度调整。自Go 1.1后,int、uint的尺寸统一是64位(即使在32位平台下)。Go 1.1的编译条件也有变化,需要在Go 1.1或以上的版本编译。
Go 1.1相比后面的版本,除语法变化比较巨大外,还做了很多性能的优化。如:
更多内联,如Append,接口类型转换;
全新实现了Map,更小的内存占用和CPU开销;
网络库性能优化,减少了上下文切换;
在标准库/工具上面,Go 1.1将一些尚未稳定的库从标准库中移除,迁移到code.google.com/p/go.exp或code.google.com/p/go.text中,并新增go/format、net/http/cookiejar、runtime/race等包。
Go 1.2语法增加了三下标切片(Three-index slices):arry[begin:end:endcap];cgo支持了C++,另外做了一些标准库compress/bzip2、crypto/dex、encoding/json等性能优化。很重要的是,Go 1.2增加了测试覆盖率。
Go 1.3,该版本几乎没有语法变化,更多的是实现细节的变化,尤其是GC。最早期的Go被诟病最多的就是GC,这和Go的策略有关系,Go较强调编程范式的稳定。和大家平常做项目一样,需要研发稳定下来的是模块之间的接口,语言的编程范式相当于大家交互的接口,该接口如稳定不下来,对后面的迭代非常有害。所以在Go 1.3的版本中,有做大量针对GC的调整,基本上做了小范围的重写。
Go在1.3之前有大量的C代码,所以它的GC其实是经验性的,如果某个整数的值恰巧是一个合法的指针,那么它会被当做一个指针来处理,这样会导致一些内存本来应该释放,当时为了安全不释放,有了这样的经验性,大部分情况已经够用。Go 1.3调整为精确GC,这会导致以前的编程手法失效。即如果有人意图把指针存储到uintptr而不是unsafe.pointer,那么这块内存无法保证不被回收;使用unsafe.pointer存储整数也不会是一个好主意,因为这会干扰GC对真相的理解。
在Map的遍历次序上,Go 1.3也做了调整,Go1标准指出,对Map的多次遍历不应该假设有同样的次序,为了避免这样的假设发生,Go 1.0遍历Map选择起点时用了随机数。Go 1.1重新实现Map后,小Map的遍历没有引入随机数,Go 1.3重新引入,以消灭此类潜在Bug。
cgo在Go 1.3中也有变化,类型不再允许跨包访问。例如,如果某个函数有 *C.FILE 参数,那么这个函数无法在其他包中使用(会编译失败),如果认为此代码是合理的,可将其调整为unsafe.pointer。
性能方面,Go 1.3大大降低了defer的内存开销;引入并行GC算法,大幅改善GC 效率;竞争检测算法(race detector)大幅提速;优化regexp包,改善大部分简单正则表达式的性能。在标准库/工具上,Go 1.3新增了debug/plan9obj包。
Go 1.4的变化看似很多,但大部分都无关痛痒。它增加了一种非常小概率使用的 forrange语法;不再自动对 **T 进行解引用(dereference);引入internal package概念;引入 canonical import paths(权威导入路径)概念。实现细节上,它开始支持安卓(编译出binary或.so);运行时(runtime)大部分用Go重写(以前是C),使得GC更加精确,同时,运行时放弃了分段栈(segmented stack)。
Go 1.5在语法上,Map字面量化写法做了变更;实现细节上,它把所有对C的依赖全部消除掉,不需要新的编译器去编Go的代码,只需要用Go的编译器,所以1.5以后编译Go的代码必须用Go,这是一个很重要的变化;GC被重写,进一步降低了GC的latency;GOMAXPROCS默认是调整为CPU数(以前是1);另外,Go 1.5开始支持iOS,为此Go team还提交了第一个Go写的AppStore应用lvy。
Go语言演进回顾
根据Go语言的几个版本,这里总结一下它的演进。
语法变化:几乎没有增加什么明显的语法特性,变化主要围绕:降低心智负担、细节完善、工程化;
Go本身迭代的核心是实现优化,主要围绕:性能、性能、性能!(重要的事情说三遍),性能的优化尤其体现在GC上,此外,还围绕更多的平台移植及更进一步的标准化,以强化社区约定。
Go和Java不一样的地方在于,Go保留了比较大的灵活性的因素。我个人对Go语言未来有这样的判断:Go介于Java和很多灵活性的语言之间。Go的语言特性,三年虽然发布了五个大版本,但其实没有什么语言的实质性变化,我见到有人喷Go时,认为Go语言太不思进取了,也有人认为Go社区对好的想法不思进取、不愿意吸收。
我认为其实不然,不止三年,哪怕是十年,Go语言的语法变化也别指望有大的改进,它基本上只会修补一些很小的地方,我觉得与其说是不思进取,不如说是它对如何写好代码这样的需求理解的自信,这是其他语言远不能企及的,也是我对Go最佩服的地方。
我为什么选Go?并不是因为Go有多好,七牛是做云服务的,云服务特别依赖并行支持,而Go可能是这世界上对并行支持的先行者。
最早七牛用Go的时候,Go 1.0还未发布,我当时对语法变化的判断不是特别高,这自信有点类似C,C到现在已经十几年了,但C到现在变过吗?几乎没什么改变,哪怕有C 99之类的,变化都很小。Go语言的想法和C很类似,我觉得很难预期 Go的语法特性变化很剧烈,但这恰恰是这个语言发展的魅力所在,因为你不用担心你写的代码三十年后会过时。从某种意义上讲,这是一种自信,它已经知道这个世界未来就应该这个样子。
Go语言的研究方向
大家都很关心Go语言未来会如何发展,我觉得三到五年内Go语言的主攻方向仍然是服务端开发,这不会有太大的变化。比如内建HTTP 2.0的支持(更多的支持会以独立的开源库的方式提供,未必直接包含在Go的发布包);另外,尽管Go已经开始支持桌面端(Mobile)的开发,但这仍然是探索性和试验性的,如果站在10年的维度上,Go语言会在桌面端(Mobile)大放异彩,占据重要地位。
很有意思的是,全球对Go最感兴趣的是中国,进一步来讲其实是华人,为什么?因为对Go感兴趣排第二的是香港,第三是新加坡,这些地方都是华人聚集地,所以Go语言在中国发展或者在华人圈发展非常不错,比在美国本土还牛很多(当然这仅仅是搜索,其实我是开玩笑的)。从开源项目的角度看,Go在国外发展的其实非常好,刚才所讲的语法特性,大家觉得发展好像很慢,但其实不然,因为它在1.0的时候就把后面的所有做的事情都想好了,后面所要做的就是优化。
下面关于Go,有一些公开的预测:
第一个预测,我最早在2012年新浪微博里提过,Go语言10年内一定会超过C和Java,变成排行榜第一的语言。今天大家可能会略相信,但在2012年的时候没有多少人会相信,即使今天讲出来,绝大部分人都会觉得太早,毕竟它还没有排进前五。
第二个预测,Go语言将在两年内制霸云计算领域。
第三个预测,Go将统治下一个 10 年。(来自于Deferpanic创始人Lan Eyberg)。
接下来一个问题,非技术人怎么看Go?第一是国外的投资人怎么看Go,我觉得国外的投资人和中国投资人不一样,他们挺技术范儿的,他们认为“开源的Go语言将成为最持久、最有广泛影响力的开源系统之一”。另外,有商务开发人士认为,“这个世界上好像几乎所有新的、有趣的项目都是用 Go写的”。
Go语言开源项目介绍
Go语言的开源项目非常多,而且绝大部分和云计算相关,我这里大致把它分为几类:一类和容器相关,第二类与微服务相关,第三类是数据库类。这三类都是基础设施,以前,大家可能认为基础设施就是操作系统、数据库,但今天的基础设施是什么?数据库和OS依然是,但云服务IaaS、PaaS也是。
大家可以看一下数据库,以前它们都是用C、C++写的(绝大部分最优广泛影响的都是用C写的),但你能想到的数据库并不多。今天,大家能看到的用Go写的数据库有多少?非常多,有键值对的、有时间序列的,还有cockrouchdb(名为小强,因为无论发生什么情况,它都不会死)等。
所以,我们今天看到,基础设施的定义已经发生了变化,实现基础设施最好的方式也发生了变化,不再是以前大家所认为的那样,系统级的东西一定是C开发的,而今天绝大部分新兴的云基础设施(甚至可以认为几乎全部都是)都是Go语言开发的。
那么,Go语言到底发展的怎么样?从Go对自己的定位来讲,它一直关注在服务端开发,服务端开发和今天的主题“云计算时代”有着非常密切的关系,Go想成为云计算时代的核心,成为大家最广泛使用的语言,从某种意义上来讲,它已经达到了。
▽
延展阅读(点击标题):
号外!号外!
阿里巴巴CTO王坚加入GTLC,全球技术领导力峰会讲师阵容再添重磅嘉宾!想一睹王坚博士风采吗?想在现场倾听他的技术领袖之道吗?就在8月GTLC全球技术领导力峰会!
点击阅读原文或扫描二维码进入GTLC官网,截止6月19日前购票,可享受7折特惠票价,此外还有双重半价优惠,更多信息,详见GTLC官网。
本文系InfoQ原创首发,未经授权谢绝转载。
文章评论