从侧面看,任何炒作都非常有趣。 当您直接参与其中时,就不会那么有趣了。
Hype Go出现在2014年的某个地方,当时拥有1000RPM(每分钟请求数)的应用程序的作者突然决定迫切需要并发,因为他们的1000RPM即将变成1000RPS(这也不是很多,实际上)。
炒作的结果是,许多习惯了该应用程序的MVC架构的人都加入了Go,无论是Spring,Django还是Ruby on Rails。 这种架构就像地球上的猫头鹰一样,开始使用Go。 因此,干部们像Beego和
Revel一样出现。 Revel安全地死了,尽管他们仍在努力将其淘汰。 但是我想分别谈论Beego。
理查德·恩格(Richard Eng)在他的系列文章
“ A Beegoist”中为在人民中推广Beego做出了重要贡献。 实际上是“理查德福音”。 具有讽刺意味的是,尽管理查德(Richard)疯狂地推广Go(Go),但他本人并未对此进行任何写作。
反过来,我与Go合作,更糟糕的是,与Beego合作,我做了很多工作。 我可以说,这显然不是Go上开发应该走的路。
让我们看一下Beego的一些基本方面,以及为什么它们与Go以及整个行业中的各种最佳实践相矛盾。
资料夹结构
罗伯特·C·马丁(Robert C. Martin),更广为人知的
鲍勃(Bob)叔叔 ,一再提出这样一个想法,即应用程序的结构应传达其本质。 他非常喜欢举一个大教堂的例子,从上面可以看到这个大教堂,并立即理解这是一座大教堂。
Robert反复批评Ruby on Rails的文件夹结构-控制器,模型,视图,仅此而已。 这种方法的问题在于,最畅销的袜子应用程序看起来就像是食品订购应用程序。 并且为了理解应用程序的本质,您将需要爬入一些models文件夹,并查看最终得到的实体类型。
重复这种病态的Beego行为。 尽管同一Spring已转向域驱动设计和文件夹结构的本质,但Beego强制使用已经成为反模式的结构。
但是问题更加严重。 对于Go,文件夹结构和包结构之间没有分隔。 因此,在Beego中,UsersController和OrdersController将在一个包中-控制器。 而且,如果您有两种类型的控制器,即服务于UI的控制器和用于API的控制器,而且在一个体面的社会中,它们通常是否版本化? 然后为apiv1之类的怪胎做好准备。
ORM
奇怪的是,作为不成功的Ruby on Rails克隆的Beego没有使用ActiveRecord模式。 他的ORM非常奇怪。 如果对于完全基本的操作(例如读一行/写一行)仍然适用,那么,例如,看起来像一个简单的示例(以下示例直接取自文档):
qs.Filter("profile__age__gte", 18)
但是Beego ORM的主要问题甚至不是您需要使用专有语言,而是它使用了所有最差的Go做法,无论它是否是导入的副作用:
import ( _ "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" _ "github.com/mattn/go-sqlite3" )
或在init()中注册模型:
func init(){ orm.RegisterModel(new(User)) }
即使您仍然出于某些莫名其妙的原因决定使用Beego,也请帮自己一个忙,不要使用Beego ORM。 如果没有ORM的生活不好(亲爱的,而您在Go的世界中正在做什么),请使用
GORM 。 至少受支持。 否则,
“数据库/ SQL”将为您提供帮助。
蜜蜂工具
命令行工具(简称为
Bee )是从Ruby on Rails复制而来的。 但是,只有在RoR的世界里有铁轨和耙子,蜜蜂才能成为所有事物的垃圾。 他和MVC应用程序一起使用“ boostrap”,并运行迁移,然后将启动文件监视程序。 后者是另一个问题。 毕竟,Go的主要优势是什么? 从本地开始的内容与在生产中开始的内容尽可能接近。 当然,如果您不使用蜜蜂。
自动路由
Go是一种强类型语言,不支持泛型或注释。 如何在此基础上构建MVC框架? 当然,通过阅读注释并生成文件。
看起来像这样:
如您所见,证据为零。 Post()函数根本不接收或返回任何内容。 http.Request? 不,没有听到。
那么,所有路由如何工作? 当您启动臭名昭著的蜜蜂时,会生成另一个文件commentsRouter_controllers.go,其中包含一个此类代码的示例:
func init() { beego.GlobalControllerRouter["github.com/../../controllers:ObjectController"] = append(beego.GlobalControllerRouter["github.com/../../controllers:ObjectController"], beego.ControllerComments{ Method: "Post", Router: `/`, AllowHTTPMethods: []string{"post"}, MethodParams: param.Make(), Filters: nil, Params: nil}) ... }
请参阅,不要忘记在每次更改后重新生成和“提交”此文件。 直到最近,情况甚至更糟,在测试过程中该文件是自动生成的,因此您已经了解了生产中的问题。 似乎在最新版本中,这种奇怪的行为已得到解决。
组件测试
因此,我们来到了测试主题。 与大多数其他编程语言不同,Go提供了开箱即用的测试框架。 通常,Go的理念是测试应位于测试文件旁边。 但是我们在MVC世界中,坚持使用Go语言,对吗? 因此,请
DHH遗赠给我们,将所有测试放在/ test爸爸中。
这不是一件小事,因为我记得在Go package ==文件夹中。 如果位于同一程序包中的测试可以调用private方法,则位于另一个程序包中的测试将不再存在。
但是,好的,一切将仅限于文件夹结构。 原则上,Beego代码很难测试,因为其中的所有内容都是副作用。
这是Beego如何查询路由器:
import ( _ "github.com/../../routers" )
我之前提到的关于中间件和控制器的故事也是如此。
该文件
这就像是我的软件架构师。 BeeGo文档和您的中文一样好。 不,过去两年来,代码中的中文注释已被删除。
现在用中文只有几个拉取请求:

特别是在问题上:

而不是结论
如果您有一个由Ruby / PHP / Python代码编写人员组成的团队,并且急需将它们翻译为Go,那么对他们来说,最糟糕的事情就是让他们切换到Go上的MVC框架。 整个MVC都是一般的架构模式,在Go中,它通常是不合适的。 或者,如果您完全确定只有Go能够拯救您,请让他们以Go接受的方式重新学习和书写-尽可能简洁明了。 或者,也许他们更了解,用什么工具来解决他们的任务?