最开始我们的业务架构是 all Python,api 服务使用 flask + celery + redis + mongdb + 基于 thrift 的 C++服务, 处理简单的图片分类。
转的原因:后面来了一个业务需求,对 api 的响应速度和 qps 都有要求,基本上是几千 qps 每秒。因为本身的业务逻辑比较简单,所以我们 profiling 了下,发现瓶颈在 Python 本身。我以前用过 Golang,所以基于 Gin 框架实现了一个简单的业务逻辑进行压测,发现性能比 Python 好很多,达到我们的预期。

工程效率对比:

  • 一个是响应时间快了不少,Python 的话能优化的空间有限,而且效果也不是很理想
  • 单机支持的 qps 提升很多,不需要增加线上的机器就可以满足新需求
    上面这两个提升基本是 5 倍左右吧,具体记不清了

然后我们基于 Golang 实现了原来的鉴别服务,达成了项目需要。

遇到的坑:

  • 包生态还不完善。我们重度依赖 Celery,Golang 当时没有类似 Python Celery 这个库,所以只能参考 Celery 的原理实现一个类似的。还有一些基于 Pandas 的代码还是保留 Python 版本。
  • Golang 的包版本管理以及下载比较麻烦,本地有代理还好,线上部署如果是实时拉代码的话很麻烦。后来我们把需要的库都本地打包到 docker 镜像里作为 base image。

其他收益

相比 Python 好的地方

  • Golang 的类型检查和基于防御性编程的错误处理方式,减少了很多 Bug 发生率,不像 Python,有时候一个错误会传递很深
  • Golang 的 goroutine 加 channel 在实现一些跟并发相关的控制逻辑时非常简洁
  • 对重构友好,完善的语法补全、定义跳转。我们的 Golang 项目都是用 vim 写的,基于 vim-go 插件,基本可以达到跟 ide 一样的效果,用 Python 的话基本不敢想象比较大的项目离开了 Pycharm 后面会变成怎么样
  • 编译速度快,支持跨平台编译,部署方便,内存占用低,长时间运行非常稳定
  • 自带 profiling 工具,性能分析方便

跟 Python 比不足的地方

  • Golang 开发效率的降低,主要是内置库没有 Python 丰富加上需要类型的缘故,会稍微繁琐一点。目测开发相同功能应该是降低到原来的 1/2 或者 1/3。但是如果算上 Golang 带来的 Bug 提早发现减少的后续开发维护工作的话,我感觉并没降低太多。毕竟修 Bug 是个很蛋疼的事情,尤其是 Python 这种
  • 测试麻烦。Python 有 mock,写测试还是比较舒服的。但是 Golang 的话,如果没有一开始就基于 interface 去思考这个代码怎么测试的话,后续写测试很蛋疼

先说优点

  1. 性能比 Python 好挺多,基本上写出来就能有不错的的性能
  2. Goroutine 和 channel 很好用,
  3. 默认静态链接,部署方便
  4. 静态类型,重构比 Python 安全很多
  5. gofmt 减少了很多关于代码风格的争论
    缺点:
  6. 表达力有点弱:动态语言在特定的问题领域可以写出很抽象的代码,实现很高的代码复用度,golang 在这方面就差了不少;没有泛型,很多时候只能靠运行时做 type cast 或者 type assertion 来解决
  7. 未使用的变量 / import 会导致编译错误,这点对调试非常不友好,有时候为了注释掉一行代码要改好几个地方
  8. 没有一个好用的包管理,使用过的里面感觉就 govendor 还能用,官方的 dep 还不成熟
  9. 没有好用的 ORM:没有像 SQLAlchemy 一样强大的 ORM (这其实算是 1 的结果)
  10. 标准库里的 errors 包没有 stacktrace (可以用 https://github.com/pkg/errors 来弥补)
  11. 一些奇怪的规则,比如 internal 包不能被外部包 import 啦,比如 append 函数暴露了 slice 的底层实现啦,比如对 slice 做 for range 遍历的第二个元素其实是 slice 中对应元素的拷贝啦等等等等;这些问题基本上只能靠多写 & 多翻语言规范来解决了(不过有些问题语言规范也写得不是很清楚 ?)

总体上来说还是比较容易上手,开发效率的话还是得看具体的任务类型,写业务的话应该不会差太多

如果是对 qps,特别是计算性能有要求的话,用 golang 没错。
如果是像 web 开发这种主要是卡在 io 上的话,用 python 也没问题。
开发效率肯定是 python 高毋庸置疑,但是动态语言也对开发者的要求比较高,水平差的写出来的 python 真的是惨不忍睹,虽然也能实现功能,但是总有一天忍不了重构的时候才会知道痛的感觉。
其实说 python 的性能问题有点过时,毕竟实在需要的地方可以上 cython。
不知道有没有人知道 uvloop,这东西用起来感觉和 go 的原生已经差不多了。(当然和 fasthttp 还有差距)
python 最大的坑是绕不开 gil,要吃满 cpu 只能多进程,如果涉及到多进程通信又是另一个大坑。

我真的不觉得 python 开发大型项目相对比 go 有优势,因为这只能是相对来说。动态语言一旦开发到一定程度,你会发现面目全非的业务逻辑,满天乱飞的全局变量,散落一地且毫无抽象的函数,见谁都恐慌的错误处理。要开发大型项目,这就十分依赖单元测试,但是说实话,很多人连基本容易测试的代码都很难写出来,单元测试覆盖率上不去,以后做重构,简直就是灾难。golang 相比 py 好的是他在工程上做了很多妥协,甚至不惜牺牲程序员的好感度, 譬如:令人蛋疼的错误处理, 简洁到没有三元运算符的语法,没有泛型等等。。。说到底,python 是一个非常信任程序员的语言,但工程角度来讲应该是不能相信任何程序员。