景区网站建设教程,专业国外网站建设,企业推广的主要目的是,定制营销的概念与方法转用一门新语言通常是一项大决策#xff0c;尤其是当你的团队成员中只有一个使用过它时。今年 Stream 团队的主要编程语言从 Python 转向了 Go。本文解释了其背后的九大原因以及如何做好这一转换。 为什么使用 Go 原因 1#xff1a;性能 Go 极其地快。其性能与 Java 或 C相似… 转用一门新语言通常是一项大决策尤其是当你的团队成员中只有一个使用过它时。今年 Stream 团队的主要编程语言从 Python 转向了 Go。本文解释了其背后的九大原因以及如何做好这一转换。 为什么使用 Go 原因 1性能 Go 极其地快。其性能与 Java 或 C相似。在我们的使用中Go 一般比 Python 要快 30 倍。以下是 Go 与 Java 之间的基准比较 原因 2语言性能很重要 对很多应用来说编程语言只是简单充当了其与数据集之间的胶水。语言本身的性能常常无关轻重。 但是 Stream 是一个 API 提供商服务于世界 500 强以及超过 2 亿的终端用户。数年来我们已经优化了 Cassandra、PostgreSQL、Redis 等等然而最终抵达了所使用语言的极限。 Python 非常棒但是其在序列化去序列化、排序和聚合中表现欠佳。我们经常会遇到这样的问题Cassandra 用时 1ms 检索了数据Python 却需要 10ms 将其转化成对象。 原因 3开发者效率不要过于创新 看一下绝佳的入门教程《开始学习 Go 语言》http://howistart.org/posts/go/1/中的一小段代码 package main
type openWeatherMap
struct
{}func (w openWeatherMap) temperature(city string) (float64, error) { resp, err : http.Get(http://api.openweathermap.org/data/2.5/weather?APPIDYOUR_API_KEYq 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} 如果你是一个新手看到这段代码你并不会感到吃惊。它展示了多种赋值、数据结构、指针、格式化以及内置的 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 的快速编译时间是一个主要的效率优势。我热爱击剑但是当我依然记得代码应该做什么之时事情已经完成就更好了。 Go 之前的代码编译 原因 6打造团队的能力 首先最明显的一点是Go 的开发者远没有 C和 Java 等旧语言多。据知有 38% 的开发者了解 Java19.3% 的开发者了解 C只有 4.6% 的开发者知道 Go。GitHub 数据表明了相似的趋势相较于 Erlang、Scala 和 ElixirGo 更为流行但是相较于 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 这样的语言但它很稳定而且你会发现在很多基础需求上已经有高质量的文件包可用了。 原因 8GOFMT强制代码格式 Gofmt 是一种强大的命令行功能内建在 Go 的编译器中来规定代码的格式。从功能上看它类似于 Python 的 autopep8。格式一致很重要但实际的格式标准并不总是非常重要。Gofmt 用一种官方的形式规格代码避免了不必要的讨论。 原因 9gRPC 和 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 改写。看下面这种排序方法的示例 {
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 代码都需要以下要求从而支持上面的排序方法 解析得分的表达。在此示例中我们想要把 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 来编写。 来源机器之心 作者Thierry Schellenbach机器之心编译参与黄小天、李亚洲 原文地址https://getstream.io/blog/switched-python-go/