Beego 的路由看起封装得很人性化,一个给人比较直观的印象是 HTTPHandleFunc 隐藏掉了 http.Response 和 http.Request 这两参数,该有功能都能方便的找到。想想每次新建一个 HTTPHandleFunc, 都要带 (w http.ResponseWriter, r *http.Request)
是一件略为繁琐的 coding 体验,我看几个项目多用了 Beego 但是都主要利用其中的 router 功能,但是随着不同项目代码维护不一,导致了升级的版本不一致而往往这几项目却部署在同一个 $GOPATH 下,比如说 A 使用了 Beego1.3 版,而 B 却升到了 1.7 版本,在编译时就会遇到问题,当然了解决方法不只一个:
- 使用不同的 $GOPATH, 主要也就是多 copy 一份 $GOPATH/src, 然后根据需要 go get 不同的版 package
- 使用 go 1.6+ 的 vendor 功能,每一个项目中优先使用自己 vendor 下面的 package
- 去 beego 化,换成其它的 HTTP router package
首先就人个看法:
- 第 1 种方法可能以后还会出现同样的问题,不推荐
- 第 2 种方法是最合适的,不像第一种需要维护整个 $GOPATH/src,项目可以根据自身的需要使用不同 package 和特定的版本,耗时少,可用性高
- 第 3 种方法在有代码性能优化需求是不错的选择,结合第 2 种方法就更好了,不过耗时会多些
最终所在项目选择迁移到 gorilla/mux
这个 router package,为什么?
反正给我的感觉就是 beego 启动太慢了,router 的吞吐效率也不太高,后来在移动完后简单的测了一下果然,beego 和 gorilla/mux 的 router 吞吐效率都不在同一个数量级上,还有就是业务不多,总得找些事去做去学习成长吧!
参考了 Beego 的 router 相关的源代码,主要改造步骤如下:
- 步骤 1: xxHTTPHandleFunc(w http.ResponseWriter, r *http.Request) -> xxHTTPHandleFunc()
- 步骤 2: TPlName 对 HTTP template 的渲染输出功能,比如 ServeJson()
- 步骤 3: 一些 request 和 response 辅助 method 的迁移实现,如 IP(),Abort(),Stop()
步骤 1 中,主要的技巧是利用 reflect 反射功能,在 ServeHTTP(w http.ResponseWriter, r *http.Request) 时进行相关的处理就 OK, 比如要的实现 Interface method 检查,panic 的处理等,不多解释直接上自己当初实践时写的 reflect demo
步骤 2 中,本来也参考了 beego 的代码,但一堆处理细节也没细看,本着 先拿到 html 文件中的模板,再对其中的占位符进行数据替换最后写入到 response 返回,这几个步骤,然而没写过这方便的代码怎么办,标准库里面有测试用例啊!就瞄了一眼 http/template 下面相关的 test case 也就明白怎么用了。
步骤 3 中的方法实现基本上也是可以直接从 beego 相关源代码中转移修改过来,问题不大
当然了,这中间有不少细节也是要注意,这里就不展开记录了,看代码会直观很多,有空再另个整理一份出来。
May 21, 2017: update
Author of beego just has written a high performace router base on Triemux recently, the entry of HTTP doesn’t fit our project, but it worth learning