放弃 Python 转向 Go语言有人给出了 9 大理由


Posted in Python onOctober 20, 2017

转用一门新语言通常是一项大决策,尤其是当你的团队成员中只有一个使用过它时。今年 Stream 团队的主要编程语言从 Python 转向了 Go。本文解释了其背后的九大原因以及如何做好这一转换。

一、为什么使用 Go

原因 1:性能

放弃 Python 转向 Go语言有人给出了 9 大理由

Go 极其地快。其性能与 Java 或 C++相似。在我们的使用中,Go 一般比 Python 要快 30 倍。以下是 Go 与 Java 之间的基准比较:

放弃 Python 转向 Go语言有人给出了 9 大理由

放弃 Python 转向 Go语言有人给出了 9 大理由

放弃 Python 转向 Go语言有人给出了 9 大理由

放弃 Python 转向 Go语言有人给出了 9 大理由

原因 2:语言性能很重要

对很多应用来说,编程语言只是简单充当了其与数据集之间的胶水。语言本身的性能常常无关轻重。

但是 Stream 是一个 API 提供商,服务于世界 500 强以及超过 2 亿的终端用户。数年来我们已经优化了 Cassandra、PostgreSQL、Redis 等等,然而最终抵达了所使用语言的极限。

Python 非常棒,但是其在序列化/去序列化、排序和聚合中表现欠佳。我们经常会遇到这样的问题:Cassandra 用时 1ms 检索了数据,Python 却需要 10ms 将其转化成对象。

原因 3:开发者效率&不要过于创新

看一下绝佳的入门教程《开始学习 Go 语言》

(http://howistart.org/posts/go/1/) 中的一小段代码:

如果你是一个新手,看到这段代码你并不会感到吃惊。它展示了多种赋值、数据结构、指针、格式化以及内置的 HTTP 库。

当我第一次编程时,我很喜欢使用 Python 的高阶功能。Python 允许你创造性地使用正在编写的代码,比如,你可以:

在代码初始化时,使用 MetaClasses 自行注册类别 置换真假 添加函数到内置函数列表中 通过奇妙的方法重载运算符

毋庸置疑这些代码很有趣,但也使得在读取其他人的工作时,代码变得难以理解。

Go 强迫你坚持打牢基础,这也就为读取任意代码带来了便利,并能很快搞明白当下发生的事情。

注意:当然如何容易还是要取决于你的使用案例。如果你要创建一个基本的 CRUD API,我还是建议你使用 Django + DRF,或者 Rails。

原因 4:并发性&通道

Go 作为一门语言致力于使事情简单化。它并未引入很多新概念,而是聚焦于打造一门简单的语言,它使用起来异常快速并且简单。其唯一的创新之处是 goroutines 和通道。Goroutines 是 Go 面向线程的轻量级方法,而通道是 goroutines 之间通信的优先方式。

创建 Goroutines 的成本很低,只需几千个字节的额外内存,正由于此,才使得同时运行数百个甚至数千个 goroutines 成为可能。你可以借助通道实现 goroutines 之间的通信。Go 运行时间可以表示所有的复杂性。Goroutines 以及基于通道的并发性方法使其非常容易使用所有可用的 CPU 内核,并处理并发的 IO——所有不带有复杂的开发。相较于 Python/Java,在一个 goroutine 上运行一个函数需要最小的样板代码。你只需使用关键词「go」添加函数调用:

package main 
import ( 
 "fmt" 
 "time")func say(s string) { 
 for i := 0; i < 5; i++ { 
  time.Sleep(100 * time.Millisecond) 
  fmt.Println(s) 
 }}func main() { 
 go say("world") 
 say("hello")}

Go 的并发性方法非常容易上手,相较于 Node 也很有趣;在 Node 中,开发者必须密切关注异步代码的处理。

并发性的另一个优质特性是竞赛检测器,这使其很容易弄清楚异步代码中是否存在竞态条件。下面是一些上手 Go 和通道的很好的资源:

https://gobyexample.com/channels

https://tour.golang.org/concurrency/2

http://guzalexander.com/2013/12/06/golang-channels-tutorial.html

https://www.golang-book.com/books/intro/10

https://www.goinggo.net/2014/02/the-nature-of-channels-in-go.html

原因 5:快速的编译时间

当前我们使用 Go 编写的最大微服务的编译时间只需 6 秒。相较于 Java 和 C++呆滞的编译速度,Go 的快速编译时间是一个主要的效率优势。我热爱击剑,但是当我依然记得代码应该做什么之时,事情已经完成就更好了。

放弃 Python 转向 Go语言有人给出了 9 大理由

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 转向 Go语言有人给出了 9 大理由

Python vs Go

我们实施的一个有趣实验是用 Python 写排名 feed,然后用 Go 改写。看下面这种排序方法的示例:

代码

Python 和 Go 代码都需要以下要求从而支持上面的排序方法:

解析得分的表达。在此示例中,我们想要把 simple_gauss(time)*popularity 字符串转变为一种函数,能够把 activity 作为输入然后给出得分作为输出。 在 JSON config 上创建部分函数。例如,我们想要「simple_gauss」调用「decay_gauss」,且带有的键值对为"scale": "5d"、"offset": "1d"、"decay": "0.3"。 解析「defaults」配置,便于某个领域没有明确定义的情况下有所反馈。 从 step1 开始使用函数,为 feed 中的所有 activity 打分。

开发 Python 版本排序代码大约需要 3 天,包括写代码、测试和建立文档。接下来,我么花费大约 2 周的时间优化代码。其中一个优化是把得分表达 simple_gauss(time)*popularity 转译进一个抽象语法树。我们也实现了 caching logic,之后会预先计算每次的得分。

相比之下,开发 Go 版本的代码需要 4 天,但之后不需要更多的优化。所以虽然最初的开发上 Python 更快,但 Go 最终需要的工作量更少。此外,Go 代码要比高度优化的 python 代码快了 40 多倍。

以上只是我们转向 Go 所体验到的一种好处。当然,也不能这么做比较:

该排序代码是我用 Go 写的第一个项目; Go 代码是在 Python 代码之后写的,所以提前理解了该案例; 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 来编写。

总结

以上所述是小编给大家介绍的放弃 Python 转向 Go语言有人给出了 9 大理由,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python实现list反转实例汇总
Nov 11 Python
Python中使用Boolean操作符做真值测试实例
Jan 30 Python
Python定时执行之Timer用法示例
May 27 Python
Python工程师面试题 与Python基础语法相关
Jan 14 Python
理解python正则表达式
Jan 15 Python
python基础_文件操作实现全文或单行替换的方法
Sep 04 Python
Python实现的直接插入排序算法示例
Apr 29 Python
解决Matplotlib图表不能在Pycharm中显示的问题
May 24 Python
对Python通过pypyodbc访问Access数据库的方法详解
Oct 27 Python
python实现简单学生信息管理系统
Apr 09 Python
python复合条件下的字典排序
Dec 18 Python
一文搞懂如何实现Go 超时控制
Mar 30 Python
python虚拟环境的安装配置图文教程
Oct 20 #Python
Python序列化基础知识(json/pickle)
Oct 19 #Python
Django ORM框架的定时任务如何使用详解
Oct 19 #Python
Python 2.x如何设置命令执行的超时时间实例
Oct 19 #Python
详解使用 pyenv 管理多个版本 python 环境
Oct 19 #Python
python3使用pyqt5制作一个超简单浏览器的实例
Oct 19 #Python
PyQt5利用QPainter绘制各种图形的实例
Oct 19 #Python
You might like
ThinkPHP3.2.2的插件控制器功能
2015/03/05 PHP
Laravel框架路由和控制器的绑定操作方法
2018/06/12 PHP
laravel邮件发送的实现代码示例
2020/01/31 PHP
拖动Html元素集合 Drag and Drop any item
2006/12/22 Javascript
教你如何解密js/vbs/vbscript加密的编码异处理小结
2008/06/25 Javascript
基于jQuery的ajax功能实现web service的json转化
2009/08/29 Javascript
js操作table示例(个人心得)
2013/11/29 Javascript
js获取下拉列表框中的value和text的值示例代码
2014/01/11 Javascript
实例分析javascript中的call()和apply()方法
2014/11/28 Javascript
JSON+Jquery省市区三级联动
2016/01/13 Javascript
EasyUI闪屏EasyUI页面加载提示(原理+代码+效果图)
2016/02/21 Javascript
Node.js的Koa框架上手及MySQL操作指南
2016/06/13 Javascript
纯css下拉菜单 无需js
2016/08/15 Javascript
功能强大的jquery.validate表单验证插件
2016/11/07 Javascript
微信小程序 video详解及简单实例
2017/01/16 Javascript
微信小程序之MaterialDesign--input组件详解
2017/02/15 Javascript
vue动态组件实现选项卡切换效果
2017/03/08 Javascript
JavaScript学习总结之正则的元字符和一些简单的应用
2017/06/30 Javascript
微信小程序学习笔记之函数定义、页面渲染图文详解
2019/03/28 Javascript
JS简单表单验证功能完整示例
2020/01/26 Javascript
Python实现的金山快盘的签到程序
2013/01/17 Python
Windows下的Jupyter Notebook 安装与自定义启动(图文详解)
2018/02/21 Python
Python3.x爬虫下载网页图片的实例讲解
2018/05/22 Python
python/sympy求解矩阵方程的方法
2018/11/08 Python
python调用c++传递数组的实例
2019/02/13 Python
Python-Seaborn热图绘制的实现方法
2019/07/15 Python
Python使用微信接入图灵机器人过程解析
2019/11/04 Python
Python matplotlib可视化实例解析
2020/06/01 Python
python和node.js生成当前时间戳的示例
2020/09/29 Python
Html5 web本地存储实例详解
2016/07/28 HTML / CSS
Perfume’s Club美国官网:西班牙第一家在线美容店
2020/06/10 全球购物
销售会计工作职责
2013/12/02 职场文书
社区优秀志愿者材料
2014/02/02 职场文书
《青海高原一株柳》教学反思
2014/04/25 职场文书
2014年小学图书室工作总结
2014/12/09 职场文书
中职班主任培训心得体会
2016/01/07 职场文书