摘要:转用一门新语言一般是一项大决策,尤为是当你的团队成员中只有一个使用过它时。今年 Stream 团队的主要编程语言从 Python 转向了 Go。本文解释了其背后的九大缘由以及如何作好这一转换。html
转用一门新语言一般是一项大决策,尤为是当你的团队成员中只有一个使用过它时。今年 Stream 团队的主要编程语言从 Python 转向了 Go。本文解释了其背后的九大缘由以及如何作好这一转换。python
Go的优点git
缘由 1:性能程序员
Go 极其地快。其性能与 Java 或 C++类似。在咱们的使用中,Go 通常比 Python 要快 30 倍。如下是 Go 与 Java 之间的基准比较:github
缘由 2:语言性能很重要golang
对不少应用来讲,编程语言只是简单充当了其与数据集之间的胶水。语言自己的性能经常无关轻重。编程
可是 Stream 是一个 API 提供商,服务于世界 500 强以及超过 2 亿的终端用户。数年来咱们已经优化了 Cassandra、PostgreSQL、Redis 等等,然而最终抵达了所使用语言的极限。json
Python 很是棒,可是其在序列化/去序列化、排序和聚合中表现欠佳。咱们常常会遇到这样的问题:Cassandra 用时 1ms 检索了数据,Python 却须要 10ms 将其转化成对象。api
缘由 3:开发者效率&不要过于创新七牛云存储
看一下绝佳的入门教程《开始学习 Go 语言》(http://howistart.org/posts/go/1/)中的一小段代码:
1 package main 2 type openWeatherMap struct{}func (w openWeatherMap) temperature(city string) (float64, error) { 3 resp, err := http.Get("http://api.openweathermap.org/data/2.5/weather?APPID=YOUR_API_KEY&q=" + city) 4 if err != nil { 5 return 0, err 6 } 7 defer resp.Body.Close() 8 var d struct { 9 Main struct { 10 Kelvin float64 `json:"temp"` 11 } `json:"main"` 12 } 13 if err := json.NewDecoder(resp.Body).Decode(&d); err != nil { 14 return 0, err 15 } 16 log.Printf("openWeatherMap: %s: %.2f", city, d.Main.Kelvin) 17 return d.Main.Kelvin, nil}
若是你是一个新手,看到这段代码你并不会感到吃惊。它展现了多种赋值、数据结构、指针、格式化以及内置的 HTTP 库。
当我第一次编程时,我很喜欢使用 Python 的高阶功能。Python 容许你创造性地使用正在编写的代码,好比,你能够:
毋庸置疑这些代码颇有趣,但也使得在读取其余人的工做时,代码变得难以理解。
Go 强迫你坚持打牢基础,这也就为读取任意代码带来了便利,并能很快搞明白当下发生的事情。
注意:固然如何容易仍是要取决于你的使用案例。若是你要建立一个基本的 CRUD API,我仍是建议你使用 Django + DRF,或者 Rails。
缘由 4:并发性&通道
Go 做为一门语言致力于使事情简单化。它并未引入不少新概念,而是聚焦于打造一门简单的语言,它使用起来异常快速而且简单。其惟一的创新之处是 goroutines 和通道。Goroutines 是 Go 面向线程的轻量级方法,而通道是 goroutines 之间通讯的优先方式。
建立 Goroutines 的成本很低,只需几千个字节的额外内存,正因为此,才使得同时运行数百个甚至数千个 goroutines 成为可能。你能够借助通道实现 goroutines 之间的通讯。Go 运行时间能够表示全部的复杂性。Goroutines 以及基于通道的并发性方法使其很是容易使用全部可用的 CPU 内核,并处理并发的 IO——全部不带有复杂的开发。相较于 Python/Java,在一个 goroutine 上运行一个函数须要最小的样板代码。你只需使用关键词「go」添加函数调用:
1 package main 2 import ( 3 "fmt" 4 "time")func say(s string) { 5 for i := 0; i < 5; i++ { 6 time.Sleep(100 * time.Millisecond) 7 fmt.Println(s) 8 }}func main() { 9 go say("world") 10 say("hello")}
Go 的并发性方法很是容易上手,相较于 Node 也颇有趣;在 Node 中,开发者必须密切关注异步代码的处理。
并发性的另外一个优质特性是竞赛检测器,这使其很容易弄清楚异步代码中是否存在竞态条件。下面是一些上手 Go 和通道的很好的资源:
缘由 5:快速的编译时间
当前咱们使用 Go 编写的最大微服务的编译时间只需 6 秒。相较于 Java 和 C++呆滞的编译速度,Go 的快速编译时间是一个主要的效率优点。我热爱击剑,可是当我依然记得代码应该作什么之时,事情已经完成就更好了。
Go 以前的代码编译
缘由 6:打造团队的能力
首先,最明显的一点是:Go 的开发者远没有 C++和 Java 等旧语言多。据知,有 38% 的开发者了解 Java,19.3% 的开发者了解 C++,只有 4.6% 的开发者知道 Go。GitHub 数据代表了类似的趋势:相较于 Erlang、Scala 和 Elixir,Go 更为流行,可是相较于 Java 和 C++ 就不是了。
幸运的是 Go 很是简单,且易于学习。它只提供了基本功能而没有多余。Go 引入的新概念是「defer」声明,以及内置的带有 goroutines 和通道的并发性管理。正是因为 Go 的简单性,任何的 Python、Elixir、C++、Scala 或者 Java 开发者皆可在一月内组建成一个高效的 Go 团队。
缘由 7:强大的生态系统
对咱们这么大小的团队(大约 20 人)而言,生态系统很重要。若是你须要重作每块功能,那就没法为客户创造收益了。Go 有着强大的工具支持,面向 Redis、RabbitMQ、PostgreSQL、Template parsing、Task scheduling、Expression parsing 和 RocksDB 的稳定的库。
Go 的生态系统相比于 Rust、Elixir 这样的语言有很大的优点。固然,它又略逊于 Java、Python 或 Node 这样的语言,但它很稳定,并且你会发如今不少基础需求上,已经有高质量的文件包可用了。
缘由 8:GOFMT,强制代码格式
Gofmt 是一种强大的命令行功能,内建在 Go 的编译器中来规定代码的格式。从功能上看,它相似于 Python 的 autopep8。格式一致很重要,但实际的格式标准并不老是很是重要。Gofmt 用一种官方的形式规格代码,避免了没必要要的讨论。
缘由 9:gRPC 和 Protocol Buffers
Go 语言对 protocol buffers 和 gRPC 有一流的支持。这两个工具能一块儿友好地工做以构建须要经过 RPC 进行通讯的微服务器(microservices)。咱们只须要写一个清单(manifest)就能定义 RPC 调用发生的状况和参数,而后从该清单将自动生成服务器和客户端代码。这样产生代码不只快速,同时网络占用也很是少。
从相同的清单,咱们能够从不一样的语言生成客户端代码,例如 C++、Java、Python 和 Ruby。所以内部通讯的 RESET 端点不会产生分歧,咱们每次也就须要编写几乎相同的客户端和服务器代码。
使用 Go 语言的缺点
缺点 1:缺乏框架
Go 语言没有一个主要的框架,如 Ruby 的 Rails 框架、Python 的 Django 框架或 PHP 的 Laravel。这是 Go 语言社区激烈讨论的问题,由于许多人认为咱们不该该从使用框架开始。在不少案例状况中确实如此,但若是只是但愿构建一个简单的 CRUD API,那么使用 Django/DJRF、Rails Laravel 或 Phoenix 将简单地多。
缺点 2:错误处理
Go 语言经过函数和预期的调用代码简单地返回错误(或返回调用堆栈)而帮助开发者处理编译报错。虽然这种方法是有效的,但很容易丢失错误发生的范围,所以咱们也很难向用户提供有意义的错误信息。错误包(errors package)能够容许咱们添加返回错误的上下文和堆栈追踪而解决该问题。
另外一个问题是咱们可能会忘记处理报错。诸如 errcheck 和 megacheck 等静态分析工具能够避免出现这些失误。虽然这些解决方案十分有效,但可能并非那么正确的方法。
缺点 3:软件包管理
Go 语言的软件包管理绝对不是完美的。默认状况下,它没有办法制定特定版本的依赖库,也没法建立可复写的 builds。相比之下 Python、Node 和 Ruby 都有更好的软件包管理系统。然而经过正确的工具,Go 语言的软件包管理也能够表现得不错。
咱们可使用 Dep 来管理依赖项,它也能指定特定的软件包版本。除此以外,咱们还可使用一个名为 VirtualGo 的开源工具,它能轻松地管理 Go 语言编写的多个项目。
Python vs Go
咱们实施的一个有趣实验是用 Python 写排名 feed,而后用 Go 改写。看下面这种排序方法的示例:
1 { 2 "functions": { 3 "simple_gauss": { 4 "base": "decay_gauss", 5 "scale": "5d", 6 "offset": "1d", 7 "decay": "0.3" 8 }, 9 "popularity_gauss": { 10 "base": "decay_gauss", 11 "scale": "100", 12 "offset": "5", 13 "decay": "0.5" 14 } 15 }, 16 "defaults": { 17 "popularity": 1 18 }, 19 "score": "simple_gauss(time)*popularity"}
Python 和 Go 代码都须要如下要求从而支持上面的排序方法:
开发 Python 版本排序代码大约须要 3 天,包括写代码、测试和创建文档。接下来,我么花费大约 2 周的时间优化代码。其中一个优化是把得分表达 simple_gauss(time)*popularity 转译进一个抽象语法树。咱们也实现了 caching logic,以后会预先计算每次的得分。
相比之下,开发 Go 版本的代码须要 4 天,但以后不须要更多的优化。因此虽然最初的开发上 Python 更快,但 Go 最终须要的工做量更少。此外,Go 代码要比高度优化的 python 代码快了 40 多倍。
以上只是咱们转向 Go 所体验到的一种好处。固然,也不能这么作比较:
Elixir vs Go
咱们评估的另外一种语言是 Elixir。Elixir 创建在 Erlang 虚拟机上。这是一种迷人的语言,咱们之因此想到它是由于咱们组员中有一个在 Erlang 上很是有经验。
在使用案例中,咱们观察到 Go 的原始性能更好。Go 和 Elixir 都能很好地处理数千条并行需求,然而,若是是单独的要求,Go 实际上更快。相对于 Elixir,咱们选择 Go 的另外一个缘由是生态系统。在咱们需求的组件上,Go 的库更为成熟。在不少案例中,Elixir 库不适合产品使用。同时,也很难找到/训练一样使用 Elixir 的开发者。
结论
Go 是一种很是高效的语言,高度支持并发性。同时,它也像 C++和 Java 同样快。虽然相比于 Python 和 Ruby,使用 Go 创建东西须要更多的时间,但在后续的代码优化上能够节省大量时间。在 Stream,咱们有个小型开发团队为 2 亿终端用户提供 feed 流。对新手开发者而言,Go 结合了强大的生态系统、易于上手,也有超快的表现、高度支持并发性,富有成效的编程环境使它成为了一种好的选择。Stream 仍旧使用 Python 作个性化 feed,但全部性能密集型的代码将会用 Go 来编写。
对每位程序员来讲,无论哪一种语言,“学的扎实,能学以至用”才是王道!本文就为对 Go 语言感兴趣的朋友们提供一些口碑不错的学习书籍建议。
1、《Go语言学习笔记》
(未找到对应版本的电子书,你们能够去做者github:https://github.com/qyuhen/book)
推荐理由:做为时下流行的一种系统编程语言,Go 简单易学,性能很好,且支持各种主流平台。已有大量项目采用 Go 编写,这其中就包括 Docker 等明星做品,其开发和执行效率早已被证实。本书经四年多逐步完善,内容覆盖了语言、运行时、性能优化、工具链等各层面知识。且内容经大量读者反馈和校对,没有明显的缺陷和错误。
适合人群:本书不适合编程初学入门,可供有实际编程经验或正在使用Go 工做的人群参考。
2、《Go语言实战》
推荐理由:William Kennedy是一位熟练的软件开发者,也是博客GoingGo.Net的做者。本书向读者提供一个专一、全面且符合语言习惯的视角。Go语言实战同时关注语言的规范和实现,涉及的内容包括语法、类型系统、并发、管道、测试,以及其余一些主题。
适合人群:全覆盖,侧重初学者
3、《Go语言编程》
推荐理由:做者是业界大神级别的人物,七牛云存储团队的核心技术人员,也是国内最先应用和推广 Go 语言技术的专家!本书内容简炼,重点突出,将 Go 语言的特性作了充分的分析和总结,并给出 Go 实例的代码;内容体系可能更适合有必定编程基础的程序员阅读!本书是国内最先的中文版的 Go 技术书籍之一,虽然发行时间比较早,但仍能够做为重要参考!电子版和纸质版都有!
适合人群:全覆盖,侧重有经验的程序员
4、《Go 语言程序设计》
推荐理由:国外最经典的Go语言著做,Go语言编程的先驱者Mark Summerfield的实践经验总结。这是一本Go语言实战指南,帮你了解Go语言,按Go语言的方式思考,以及使用Go语言来编写高性能软件。
做者展现了如何编写充分利用Go语言突破性的特性和惯用法的代码,以及Go语言在其余语言之上所作的改进,并着重强调了Go语言的关键创新。
注重实践教学,每章都提供了多个通过精心设计的代码示例。
由国内第一个核心服务彻底采用Go语言实现的团队——七牛团队核心成员翻译。
适合人群:适用于有必定Go语言编程编程的爱好者,很是适合做为Go语言编程进阶教程。