17611538698
webmaster@21cto.com

从 PHP 转到 Go ?是亵渎,是虚张声势还是常识?

资讯 0 3032 2017-05-23 12:01:31
focus-go.png

21CTO社区导读:
本文作者以实例的方式演示Go语言开发的灵活,高效。他以PHP的Laravel框架与Go的原生写法进行对比,显然有一些偏颇。虽然如此,但是Go语言的魅力是越来越强大了。



074141_jBeY.png

前段时间,我做了一个艰难的决定,我决定用Go重写了Boxzilla的应用,以前是用PHP的Laravel框架开发的。
不要后悔

/uploads/fox/23075103_1.jpg
在几个星期后,部署了Go应用程序。后来,我测试了一下结果 ,发现比旧的应用有很大的改进,包括更好的性能,更容易部署。

这个应用程序是一个比较简单的数据库驱动的API和用户帐户系统:用户可以登录来下载产品,查看订购的发票,更换付款方式等。

我用Stripe和Braintree两个网关来接受在线支付,发票使用MoneyBird处理,邮件我使用了Mailgun来发送。
当我用Laravel完成项目后,但总觉得有些事情有点复杂。

Laravel每隔一段时间就会发布一个新的版本,告诉我包含了哪些明显的改进,性能又提升了多少倍,会非常好。但很多时候,我觉得它只是对命名和目录结构的更改。

为什么用Go?

去年,我已经把几项服务移到Go上。 但是我还在使用PHP来做产品,比如销售WordPress的二次开发,这个看似古老的技术堆栈,最终卖给最终用户。
如果我是一个自雇者,我会选择一个新的技术来开始我的工作。但是我的老板需要我每天好好工作赚钱。如果条件允许,你想不想有一些新色彩?

而写Go代码就是一种乐趣,它不仅可以快速开发,性能也是快速的。

我想未来几年内,会看到更多人从PHP,Python和Java等动态类型语言切换到Go。

移植代码库

把代码移植到Go语言,主要是数据库的交互,把Laravel中的Blade模板移植到Go中可以使用的东西。
ORM是我比较喜欢的方式,将一些麻烦的数据访问层和纯SQL查询移除。Meddler被用来处理查询结果映射为结构体的模板。
为了像Laravel一样支持多层模板,我用Go封装了一个HTML模板类叫做Grender,现已经开源,它的地址在https://github.com/dannyvankooten/grender
想在应用中集成Strpe,Strpe官方提供了stripe-go(https://github.com/stripe/stripe-go) 这个包。对于Braintree,有一个叫braintree-go(https://github.com/lionelbarrow/braintree-go)的包,以前更新的不太勤,现在又有了新关注。

另外,Go没有软件包,提供管理Moneybird的发票,我还开源了moneybird-go(https://github.com/dannyvankooten/moneybird-go)。

苹果和桔子的比较

其实Go一个编译型的语言,会好于运行在标准库下解释型的PHP。其实这样比较对PHP是不公平的。但是,我需要分享一些数据,可能会更有趣。
性能
我们使用wrk来测试两个应用的登录页面的性能基准测试。ConcurrencyAvg. latencyReq / secTransfer / sec Laravel13.87ms261.481.27MBLaravel100108.86ms917.276.04MBGo1325.72μs7365.4834.27MBGo10011.63ms19967.3192.91MBGo20037.68ms22653.22105.41MB
通过上面的表格,我们看到Laravel(或PHP-FPM)在超过了100个并发数据时,性能出现了一些下降。
使用NetData显示出如下图表,可以了解服务器在这些负载时的状态。

Golang有100个并发连接的状态图:

074143_o7ks.jpeg


Laravel有100个并发连接的状态图:


074143_MCRZ.jpeg



请注意,我运行的是与运行应用程序相同的机器的基准测试,所以这极大地影响了这两个图形。

关于代码

我们来比较一下两个应用的代码行数据,包括第三方依赖。

find . -name '*.php' | xargs wc -l
156289 total


Laravel超过156000行代码。这还不包括使用Laravel进行测试的依赖包。

find . -name '*.go' | xargs wc -l 
33624 total


另一方面,Golang版本由33.000行代码组成。 这是完全相同功能的代码的五分之一。
我们在Laravel应用程序中排除外部依赖关系,所以我们知道我实际写了多少行。

find . -name '*.php' -not -path "./vendor/*" | xargs wc -l 13921 total


对于Go语言来说:

find . -name '*.go' -not -path "./vendor/*" | xargs wc -l 6750 total


即使是在ide中的代码视图,可能结果会有所增加。不过,相同功能的应用,Go只有一半的代码量。

测试工具

在单元测试中,我们使用是Go提供的citizen类,由以下4个文件组成:

license.go
license_test.go
subion.go
subion_test.go


 
这使得它能非常方便的使用测试驱动开发。
在我们的Laravel应用中我们主要有集成测试来检查请求处理器是否返回了正确的响应。整体测试覆盖率相当的低, 主要是由于紧耦合,当然这主要是我的错。第二次编写同样的应用程序时,这里有了很大的改善。


小结

其实我做了不应该做的事情,用不同的语言重写一个应用。因为我觉得这样会有更多的乐趣,而且又有小而快的应用程序作为回馈。
 
 

作者:Danny van Kooten
来源:https://www.sitepoint.com/moving-php-go/


评论