β

Go: An Innovation in Programming Practice

Harries Blog™ 41 阅读

Go: An Innovation in Programming Practice

Go is not meant to innovate programming theory. It’s meant to innovate programming practice.

– Samuel Tesla [1]

所有关于 Go语言 的quotes中,笔者最喜欢的是这一句。

Go是一门挺有意思的语言,它诞生于 Google ,2009年底推出后曾经经历了短暂的热议,而后又归于沉寂,直到今年又才重新升温。T IO BE Index[2]给出的Go语言热度如下所示:

Go: An Innovation in Programming Practice

相比Java、C/C++这些老牌语言,Go还只能算是编程语言中的“小弟”,直到今年11月才刚刚爬到TIOBE Index历史最高的第13位:

Go: An Innovation in Programming Practice 这可能是近年来崛起的一些基于Go语言的项目,例如 Docker [3]、 Kubernetes [4]的功劳。

Go语言设计者之一Rob Pike在2012年接受采访时曾经道出了一段往事:其实Go语言设计之初是为了替代C++的。结果令人尴尬的是,C++的 程序员 们反应冷淡(“don’t seem to care”),来用Go的程序员们大多来自Python和Ruby。[5]

但笔者却正好是个反例。作为一名以C++为“母语”的程序员,当笔者接触到了Go语言后,确实有一种打开了新世界窗户的感觉,并认为“C++基本上可以扔了”。因为 在Go语言的设计中总是处处体现着Google在 开发 中的 (best) practice ,而这也正是笔者所梦寐以求的。(从这个意义上来说,Rob Pike们可以安心了,总有人懂你们!)

本文不做Go语言入门,也不做语言优劣之争,只谈笔者个人对Go语言的感受,以及对Go语言在编程实践方面的理解:

1,Google 编译 体系的复刻

可能有不少刚接触Go语言的人会问这样一些问题:为什么要有GOPATH这样一个东西?编译的时候指定项目 目录 不就好了吗,为什么要弄一个目录放置所有Go 代码 ,再设置一个全局变量告诉Go编译器这个目录在哪?为什么 GOPATH 下要分 src /bin/pkg三个目录?其实这些都源自Google独特的单根代码库开发模式及其配套的编译构建体系(参见拙著《从Google的单代码库模式看Google工程文化》[6])。Go的代码 管理 就像Google的单根管理形式。Go编译器的基本命令,例如go build 、go test等,长得就像Google的blaze编译系统(已 开源 为bazel[7])那样。另外,Go语言还有go get/install命令进行包管理。

这些让笔者感到非常熟悉和亲切。在Google进行C++开发是件非常轻松的事情:基础库做得非常完善(绝大多数都是自己写的),依赖管理也做得非常好,编译构建架构成熟且易用。但在Google外做C++开发会发现有许多困难,比如C++的依赖管理是让人很头疼的事情,而且经常碰到二进制版本不兼容的问题。又比如make file是一件很“反人类”的东西,远远没有blaze/bazel的B UI LD file易用。Go语言借鉴了Google在这方面的经验,从语言工具的层面解决了这些问题。

2,集成了单元 测试

这一点笔者想单独拎出来说说。C++自身没有什么单元测试框架,但单元测试对于 质量 保证实在太重要了。Go语言自带testing包,结合go test命令可以完美运行单元测试,整套东西基本上就是gtest[8] + blaze test的复刻版,用起来十分的简单。

3,较为统一的Coding Style

统一的coding style有利于团队协作和代码的可维护性。Go语言的coding style一直以来是争议比较大的,因为有许多语法层面的规定,例如小写开头的任何变量(包括函数)都是package scope的(类似Java里面public/protected/private什么都不加那种),大写开头的任何变量都是public的(类似Java里的public)。又比如花括号的开头必须放在前一行的末尾,而不能放在下一行的开头独占一行(后者甚至不能编译!)。这些规定限制了代码风格的多样性,有利于统一风格。另外,Go语言提供了程序格式化工具go fmt,会自动对程序进行一定程度上的风格归一化(例如空格变 tab ,import按字典序排序等)。

不过不像其它主流语言在Google都有非常详尽的coding style[9],目前Go语言没有推出过官方“细致版”coding style,只有《Effective Go》[10]和[11]算是官方的一些指导性建议,所以Go语言的coding style只能算是“较为统一”的。(这里顺带吐槽一下Go语言的许多coding style建议 似乎是 与Google其它语言背道而驰的。例如Go语言用tab而不用space,偏向用短变量名而非更具描述性的长变量名。笔者至今没有想通为什么…)

4,为微服务而生

微服务(Microservice)模式近年来随着分布式计算和Docker等技术的发展而火热起来。微服务之间的调用需要RPC。作为Google的亲儿子,Google在其开源的RPC框架gRPC[12]中理所当然的加入了对Go语言的支持。不过Go语言表示:我自己也天生带RPC框架的。Go语言的net/rpc包中自带了RPC框架,可以通过gob(Go语言的object编码格式)、 json 或用户自定义的编码格式进行RPC调用,开发起来非常的简便。不过,Go语言自己的RPC只针对Go语言写的服务有效,如果要跨语言还是要用gRPC,通过protocol buffers做 数据 交换。

另外,出于Google的习惯(C++亦是如此),Go语言默认采用static linking的方式生成binary。这意味着部署的时候无需担心 服务器 上是否有外部依赖的动态链接库,只需一个binary一切搞定。因此,即使没有Docker这样的容器框架保障部署环境,Go产出的binary依旧能更容易的独立工作。

5,Share memory by communi cat ing, do not communicate by sharing memory

这是concurrent programming中的一个原则,在Go语言标志性的 goroutine+channel模式 下体现得淋漓尽致。而且goroutine+channel+select的模式让concurrency变得难以置信的简单,可以轻松启动大量并行任务,无需像在其它语言里那样考虑 线程 / 线程池 的创建和维护;可以轻松实现服务中经常出现的timeout、cancel、fan out query等逻辑(如果有兴趣可以参考[13]、[14]、[15])。

6,White-box Monitoring

监控也是服务稳定性相当重要的一环。White-box monitoring指直接监控系统内部指标的监控方式。在Google运行的所有service都会自带一个 http 的varz服务,其中可以暴露很多服务的关键指标,然后通过borgmon收集、 统计 ,在出现异常时报警。 [16]

Go语言也自带了类似的功能。通过expvar包,你可以轻松的将自己认为重要的系统关键指标暴露出来(默认暴露到http://你的服务 ip :port/debug/vars),既方便人肉查看,也可以通过Prometheus[17]等监控框架收集数据,做监控和报警。

7,Profiling

Profiling是查找程序瓶颈,提高程序效率的重要手段。Google有C++版本的profiling tool[18],Go语言也继承了这个传统,通过runtime/pprof包和go tool pprof可以方便的对程序进行profiling。同时类似expvar包,Go语言还可通过net/http/pprof包实现用http服务暴露pprof数据( 默认暴露到http://你的服务ip:port/debug/pprof ),方便数据的查看和收集。

结语

诞生于Google的Go语言天生就是Google编程实践的集成者,尽管也有一些令人头疼的地方(以后有机会再说,嘿嘿),它还是让笔者倍感亲切和惊喜!

[1] 摘自 Ivo Balbaert 《 The Way to Go: A Thorough Introduction to the Go Programming Language》

[2] http://www.tiobe.com/tiobe-index/

[3] https ://www.docker.com/

[4] http://kubernetes.io/

[5] https://commandcenter.blogspot.de/2012/06/less-is-exponentially-more.html

[6] http://dwz.cn/4ItEZv

[7] https://bazel.build/

[8] https:// git hub.com/google/googletest

[9] https://github.com/google/stylegu id e

[10] https://golang.org/doc/effective_go.html

[11] https://github.com/golang/go/wiki/CodeReviewComments

[12] http://www.grpc.io/

[13] https://blog.golang.org/go-concurrency-patterns-timing-out-and

[14] https://blog.golang.org/pipelines

[15] https://blog.golang.org/context

[16] Betsy Beyer, et al.《Site Reliability Engineering: How Google Runs Production Systems》

[17] https://prometheus.io/

[18] https://github.com/gperftools/gperftools

原文

http://mp.weixin.qq.com/s/dJ8bJGiqtKeQr6sdXtzZBA

PS:如果您想和业内技术大牛交流的话,请加qq群(521249302)或者关注微信公众 号(AskHarries),谢谢!

转载请注明原文出处: Harries Blog™ » Go: An Innovation in Programming Practice

作者:Harries Blog™
追心中的海,逐世界的梦
原文地址:Go: An Innovation in Programming Practice, 感谢原作者分享。

发表评论