写点什么

从 Python 切换到 Go 的 9 个理由

  • 2020-04-16
  • 本文字数:4832 字

    阅读完需:约 16 分钟

从Python切换到Go的9个理由

AI 大模型超全落地场景&金融应用实践,8 月 16 - 19 日 FCon x AICon 大会联诀来袭、干货翻倍!

切换到一种新的编程语言通常是一件大事,特别是当团队成员对原始语言有丰富经验时。今年年初,Stream将其主要编程语言从 Python 切换到了 Go。本文将会解释他们决定从 Python 切换到 Go 的一些原因。

使用 Go 的理由

理由 1:性能


Go 非常快。它的性能接近 Java 或 C。Go 的速度比 Python 快 30 倍。

理由 2:语言本身的性能很重要

对于许多应用程序而言,编程语言只是应用程序和数据库之间的粘合剂。语言本身的性能通常并不重要。


Stream 是一家 API 提供商,它为 500 家公司和超过 2 亿的最终用户提供了反馈基础设施。多年来,我们一直在优化 Cassandra、PostgreSQL、Redis 等软件的性能,但是现在我们已经达到了我们所使用编程语言的极限。


Python 是一门伟大的语言,但是对于序列化/反序列化、排序和聚合等示例,它的性能非常差。我们经常会遇到性能问题,Cassandra 花费 1ms 的时间来检索数据,而 Python 将其转换成对象则需要 10ms 的时间。

理由 3:开发人员的效率,而无需太多创新

请看下“如何开始学习Go”教程中的如下 Go 代码片段。


type openWeatherMap struct{}func (w openWeatherMap) temperature(city string) (float64, error) {    resp, err := http.Get("http://api.openweathermap.org/data/2.5/weather?APPID=YOUR_API_KEY&q=" + city)    if err != nil {        return 0, err    }    defer resp.Body.Close()    var d struct {        Main struct {            Kelvin float64 `json:"temp"`        } `json:"main"`    }    if err := json.NewDecoder(resp.Body).Decode(&d); err != nil {        return 0, err    }    log.Printf("openWeatherMap: %s: %.2f", city, d.Main.Kelvin)    return d.Main.Kelvin, nil}
复制代码


如果你刚开始学习 Go,阅读这段代码不会有太多惊喜。它演示了赋值、数据结构、指针、格式化和内置的 HTTP 库。


从我首次接触编程开始,我总是喜欢使用 Python 的高级特性。 Python 使我们能从正在编写的代码中获得很好的想法。例如,我们可以:


  • 初始化代码时,使用元类(MetaClasses)自己注册类

  • 切换“True”和“False”

  • 将一个函数添加到内置函数列表中

  • 通过魔术方法(Magic Method)重载运算符


这些特性非常有趣,但是,大多数程序员都认为这会增加阅读他人代码的难度。


Go 会迫使我们使用最基本的东西,这使得阅读他人代码变得更容易。


注:当然,“容易”取决于具体的项目。如果只是创建一个基本的 CRUD API,我仍然建议使用 Django&DRF或 Rails。

理由 4 :并发和通道

作为一门编程语言,Go 总是尽可能地保持简单。它没有引入太多的新概念,因为它的目标是创建一门易于使用的编程语言。它唯一具有创新性的地方是 Goroutines(go 协程)和 Channels(通道)。 Goroutines 是 Go 的轻量级线程解决方案,而 Channels 是与 Goss 交互的首选方式。


Goroutines 非常轻量,仅需要几千字节的额外内存。而且由于 Goroutine 如此轻量,因此可以同时运行数百甚至数千个 Goroutine。


我们可以使用 Channels 在 Goroutines 之间进行通信。Go 运行时处理所有的内部复杂性。基于 Goroutines 和 Channels 的并发方案使应用程序能够轻松使用所有可用的 CPU 内核并处理并发 IoO,而无需进行复杂的开发。与 Python/Java 相比,在 Goroutines 上运行函数只需要很少的固定代码。我们只需要使用关键字“go”调用函数即可:


package mainimport (    "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")}
复制代码


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


Go 的并发解决方案非常易于使用。与开发人员必须密切关注异步代码处理方式的 Node 相比,这是一个非常有趣的方案。


Go 并发的另一个关注点是竞态检测。它使应用程序能够很容易地知道异步代码中是否存在任何竞态条件。


以下是一些学习 Go 和 Channels 的重要资源:


理由 5:编译速度快

用 Go 编写的最大的微服务项目只需 6 秒就可以编译完成。与 Java 和 C 等语言的龟速(turtle-speed)编译相比,Go 的极快编译速度是它的主要生产力。

理由 6:组件团队的能力

让我们从这些数据开始:Go 的开发人员没有 C 和 Java 的开发人员多。根据StackOverflow的统计,有 38%的开发人员使用 Java,19.3%的开发人员使用 C,但只有 4.6%的开发人员使用 Go。 GitHub数据也显示出了类似的趋势:Go 比 Erlang、Scala 和 Elixir 等语言使用得更广泛,但不如 Java 和 C 那么流行。


幸运的是,Go 是一门非常简单易学的语言。它只提供了我们需要的基本功能,而没有提供其他附加功能。它引入了一些新概念,例如“defer”声明和内置的“go routines”以及 Channels 并发管理等。团队中的任何 Python、Elixir、C、Scala 或 Java 开发人员都可以在一个月内学习会怎么使用 Go 编程,因为 Go 非常简单。


与其他语言相比,我们发现建立 Go 开发团队更加容易。如果我们在竞争激烈的环境中(例如在博尔德和阿姆斯特丹)招聘,这是一个非常重要的优势。

理由 7:强大的生态系统

生态系统对于我们这样规模的团队(大约 20 人)来说非常重要。如果你不得不重新设计所有的功能,你就不能为你的客户创造价值。Go 为我们经常使用的工具提供了强大的支持。例如,Redis、RabbitMQ、PostgreSQL、模板解析、任务调度、表达式解析和 DBRocks 都可以使用现有的库。


与其他新语言(例如 Rust 或 Elixir)相比,Go 具有巨大的生态系统优势。尽管它不能与 Java、Python 或 Node 相提并论,但是我们是可以找到许多能够满足基本需求的高质量软件包。

理由 8:Gofmt,强制代码格式化

Gofmt 是一个优秀的命令行程序,它内置于 Go 编译器中,可用于格式化代码。在功能方面,它类似于 Python 的 autopep 8。我们大多数人都不喜欢争论制表符(tabs)和空格(spaces),但格式化的目标始终是一致的,实际的格式标准则无关紧要。Gofmt 以一种形式化的方式来格式化代码,以避免所有这些争论。

理由 9:gRPC 以及 Protocol Buffers

Go 为 Protocol Buffers 和 gRPC 提供了一流的支持。它将这两个工具完美地结合在一起,构建了一个通过 RPC 进行通信的微服务。我们只需编写一个定义了 RPC 调用及其参数的清单文件,服务端和客户端就可以据此自动生成适当的代码了。这不仅速度快,而且网络占用空间小,使用起来更方便。


其他语言(如 C、Java、Python 和 Ruby)中的客户端代码也可以基于相同的清单文件生成。这样,就不会与内部 REST 接口发生冲突了,而且我们也不必每次都编写几乎相同的客户端和服务端代码。

使用 Golang 的缺点

缺点 1 :缺乏框架

Go 不像 Ruby 的 Rails、Python 或 Django 或 PHP 的 Laravel,它没有一个主要的框架。这个话题在 Go 社区引起了激烈的争论,许多人认为不应该使用现有的框架来启动项目。在某些情况下,我完全同意这一点。但是,如果我们想要构建一个简单的 CRUD API,那么使用 Django/DJRF、Rails Laravel 或Phoenix则会更简单。

缺点 2:错误处理

Go 通过简单地从函数中返回错误的形式来处理错误。尽管这种方案是可行的,但是它很容易失去错误的范围,从而很难向用户提供有价值的错误信息。错误包可以通过返回错误的上下文和错误堆栈来解决该问题。


还有一个问题,那就是它很容易忘记去处理错误。尽管诸如 errcheck 和 megacheck 之类的静态分析工具可以避免这些错误,但这始终并不完善。也许我们应该期待一种语言级别的错误处理方案。

缺点 3:包管理

Go 的包管理并不完善。默认情况下,它无法指定依赖项的特定版本,也无法创建可重用的构建方案。 Python、Node 和 Ruby 都有更好的包管理系统。但是,如果能使用正确的工具,Go 的包管理也可以变得更简单。


我们可以使用Dep来管理指定固定版本的依赖项。此外,我们还提供了一个名为VirtualGo的开源工具,用于多项目管理。

Python vs Go

我们做了一个有趣的实验,用 Go 重写了原来由Python编写的feed流。请看一下该排序方法的示例:


{    "functions": {        "simple_gauss": {            "base": "decay_gauss",            "scale": "5d",            "offset": "1d",            "decay": "0.3"        },        "popularity_gauss": {            "base": "decay_gauss",            "scale": "100",            "offset": "5",            "decay": "0.5"        }    },    "defaults": {        "popularity": 1    },    "score": "simple_gauss(time)*popularity"}
复制代码


Python 和 Go 的代码都需要执行如下操作来支持此排序方法:


  1. 解析分数表达式,将“simple_gauss”转换为函数,输入活动并输出分数

  2. 通过 JSON 配置创建函数。例如,我们想要“simple_gauss”在 scale 为 5 天、offset 为 1 天、factor 为 0.3 时调用“decay_gauss”。

  3. 当字段没有值时,解析“defaults”配置并采用默认值。

  4. 从步骤 1 开始使用该函数,对 feed 中的所有活动进行评分。


开发 Python 版的排序(Sort )代码花了大约三天的时间,其中包括代码编写、单元测试和文档编写。接下来,我们花了大约 2 周的时间来优化代码。其中一种优化方法是将分数表达式 simple_gauss(time)*popularity 转换为抽象语法树。我们还实现了可用于预测分数的缓存逻辑。


相比之下,开发此代码的 Go 版花了大约四天的时间,并且在后期不需要进一步地优化性能。因此,尽管 Python 最初的开发速度更快,但是 Go 版最终需要的工作量更少。另一个优势是,Go 代码比我们高度优化的 Python 代码还要快 40 倍。


当然,这只是说明我们切换到 Go 后性能提升的一个简单示例:


  • 排序代码是我用 Go 编写的第一个项目。

  • Go 代码是在 Python 代码之后编写的,因此对项目的理解更加深入。

  • Go 的表达式解析库的质量更高


你的经历可能会有所不同。与 Python 相比,使用 Go 构建系统中的某些其他组件需要花费更多的时间。通常,编写 Go 代码需要付出更多的努力。但是,优化代码性能所需的时间会更少。

Elixir vs Go

我们想要评估的另一种语言是Elixir。 Elixir 是一门建立在 Erlang 虚拟机上的引人入胜的语言。我之所以这么说,是因为我们的一个项目团队非常精通该语言。


出于这个原因,我们注意到 Go 的原始性能更好。 Go 和 Elixir 都能支持数千个并发请求。但是,如果我们查看单个请求的性能,Go 要快得多。我们选择 Go 的另一个原因是它的生态系统。 对于我们需要的组件来说,Go 具有更成熟的库,而 Elixir 尚不适合用于生产。同时,也很难招聘到 Elixir 开发人员或对开发人员进行 Elixir 培训。

结论

Go 是一种性能非常高的语言,并且它对并发的支持非常强大。它差不多与 C 和 Java 一样快了。尽管 Go 的编译速度比 Python 或 Ruby 慢,但我们可以节省出大量的优化代码时间。


Go 对于新手而言具有庞大的生态系统,它易于学习使用,具有超高的性能,并且对并发有强大的支持,此外,它还具有非常高效的开发环境。这些特性使 Go 成为开发人员最合适的选择。


如果你想要了解更多关于 Go 的信息,请阅读下面列出的文章。如果想了解更多关于 Stream 的信息,请浏览此交互式教程


相关阅读:



Go 学习资料:



原文链接:


Nine reasons to switch from Python to Go


2020-04-16 09:0015786

评论 1 条评论

发布
用户头像
emmm '缺点 3:包管理' 现在有go modules
2020-04-24 17:00
回复
没有更多了
发现更多内容

为什么我在公司里访问不了家里的电脑?

做梦都在改BUG

Java 计算机网络 网络协议

奇安信首次盈利,网络安全国家队将迎来收获期?

ToB行业头条

网络安全

打造合规数据闭环,加速自动驾驶技术研发

Baidu AICLOUD

自动驾驶 数据闭环

1 理解功能、业务功能和能力

涛哥 数字产品和业务架构

企业架构 业务架构 业务架构师

佛萨奇系统开发源码部署技术方案(MetaForce元宇宙)

I8O28578624

2024最新easyrecovery数据恢复软件免费版

茶色酒

EasyRecovery15

特定领域知识图谱融合方案:文本匹配算法(Simnet、Simcse、Diffcse)

汀丶人工智能

自然语言处理 知识图谱 2月日更

北京大数据培训中心怎么样

小谷哥

从实测出发,掌握 NebulaGraph Exchange 性能最大化的秘密

NebulaGraph

数据导入

顶会论文 | 虚拟网络探测技术的探索与实践

阿里技术

网络运维 虚拟网络探测

TiDB 6.5 新特性解析丨过去一年,我们是如何让 TiFlash 高效又稳定地榨干 CPU?

PingCAP

TiDB

2023 年推荐这 10 个开发者工具

Liam

前端 后端 开发者工具 开发工具 程序员 java

零基础前端培训学习有用吗

小谷哥

过年回去,终于给老人讲清楚两台电脑是如何通信的

华为云开发者联盟

后端 开发 华为云 企业号 2 月 PK 榜 华为云开发者联盟

国资委79号文解读:国央企OA办公系统信创替代落地实践与标杆案例

数字科技时讯

信创 电子合同 电子签名 企业国产化 OA

百度智能云助力自动驾驶全链路研发

Baidu AICLOUD

自动驾驶 全链路

开发小白的高光逆袭:竟然能一眼断定生产环境接口响应时间慢是磁盘性能问题引起的

KINDLING

Java 故障定位 ebpf 生产环境 排障

城市健康云,打造大健康服务生态

华为云开发者联盟

云计算 后端 华为云 企业号 2 月 PK 榜 华为云开发者联盟

如何将使用中的域名平滑迁移到京东云?(以原域名注册、域名解析都在万网为例)

京东科技开发者

域名解析 注册 京东云 京东商城 企业号 2 月 PK 榜

会声会影2023中文版操视频剪辑软件下载

茶色酒

会声会影2023

PingCAP 黄东旭万字长文剖析数据库发展新趋势:脱离应用开发者的数据库,不会成功

PingCAP

数据库 TiDB

重塑设备维护管理的主要趋势

PreMaint

设备健康管理 设备管理

采购LED显示屏时必须了解哪些技术参数?

Dylan

LED显示屏 全彩LED显示屏 led显示屏厂家

随机高并发查询结果一致性设计实践

京东科技开发者

架构设计 并发 业务场景 企业号 2 月 PK 榜 京东物流

软件研发效能管理工具有哪些?8大效能管理工具盘点

易成管理学

企业管理 管理软件 效能管理

软件测试/测试开发 | app自动化测试(Android)--触屏操作自动化

测试人

软件测试 自动化测试 测试开发 appium

java就业培训班怎么选?

小谷哥

如何解决Mac电脑突然变得又卡又慢的处理方法

茶色酒

自动驾驶工具链及仿真平台的应用

Baidu AICLOUD

自动驾驶 工具链

软件测试/测试开发 | app自动化测试(Android)--显式等待机制

测试人

软件测试 自动化测试 测试开发 appium app自动化测试

跨境电商“重新出发”,区块链赋能新玩法

旺链科技

区块链 区块链技术 区块链技术应用

从Python切换到Go的9个理由_编程语言_Shiv McIntyre_InfoQ精选文章