Golang 使用 Beego 与 Mgo 开发的示例程序
博客原文出处:http://wuwen.org/article/3/sample-web-application-using-beego-and-mgo当我发现 beego 框架时感觉非常激动。我只用了大约 4 个小时就将一个现有的 Web 应用程序移植到了该框架上并做了一些端对端测试的调用扩展。我想要与你分享这个基于 beego 的站点。我构建了一个具有以下功能的示例 Web 应用程序:
这个示例的代码可以在 GoingGo 帐户下的 GitHub 仓库中找到:https://github.com/goinggo/beego-mgo。 你可以拉取并运行它。它使用了我在 MongoLab 创建的公开 MongoDB 数据库。你会需要安装 git 和 bazaar 以保证能够使用 go get 来将它安装到你系统中。 go get github.com/goinggo/beego-mgo
使用 zscripts 文件夹里的脚步可以快速运行或测试 Web 应用程序。 Web 应用程序代码结构让我们来看一下项目结构和不同文件夹的功能:
控制器、模型和服务这些层的代码组成了 Web 应用程序。我的框架背后的理念是尽可能的抽象化代码为样板。这就要求我实现一个 base 控制器包和 base 服务包。 base 控制器包base 控制器包由所有控制器所要求的默认抽象的控制器行为来组成: type ( BaseController struct { beego.Controller services.Service } ) func (this *BaseController) Prepare() { this.UserId = "unknown" tracelog.TRACE(this.UserId,"Before","UserId[%s] Path[%s]",this.UserId,this.Ctx.Request.URL.Path) var err error this.MongoSession,err = mongo.CopyMonotonicSession(this.UserId) if err != nil { tracelog.ERRORf(err,this.Ctx.Request.URL.Path) this.ServeError(err) } } func (this *BaseController) Finish() { defer func() { if this.MongoSession != nil { mongo.CloseSession(this.UserId,this.MongoSession) this.MongoSession = nil } }() tracelog.COMPLETEDf(this.UserId,"Finish",this.Ctx.Request.URL.Path) } 一个名为 服务包服务包用于样板化所有服务所要求的代码: type ( Service struct { MongoSession *mgo.Session UserId string } ) func (this *Service) DBAction(databaseName string,collectionName string,mongoCall mongo.MongoCall) (err error) { return mongo.Execute(this.UserId,this.MongoSession,databaseName,collectionName,mongoCall) } 在 实现一个 Web 调用基于 base 类型和样板函数,我们现在可以实现一个 Web 调用了: Buoy Controller类型 type BuoyController struct { bc.BaseController } func (this *BuoyController) Station() { buoyBusiness.Station(&this.BaseController,this.GetString(":stationId")) } BuoyController 直接由单独的 函数 beego.Router("/station/:stationId",&controllers.BuoyController{},"get:Station") Station 会在底层调用 business 层的代码来处理请求。 Buoy BusinessBuoy Business 包实现了 func Station(controller *bc.BaseController,stationId string) { defer bc.CatchPanic(controller,"Station") tracelog.STARTEDf(controller.UserId,"Station","StationId[%s]",stationId) buoyStation,err := buoyService.FindStation(&controller.Service,stationId) if err != nil { ServeError(err) return } controller.Data["json"] = &buoyStation controller.ServeJson() tracelog.COMPLETED(controller.UserId,"Station") } 你可以看到 business 层的函数 Buoy ServiceBuoy Service 包实现了与 MongoDB 的交互。让我们来看下被 business 层的函数 func FindStation(service *services.Service,stationId string) (buoyStation *buoyModels.BuoyStation,err error) { defer helper.CatchPanic(&err,service.UserId,"FindStation") tracelog.STARTED(service.UserId,"FindStation") queryMap := bson.M{"station_id": stationId} tracelog.TRACE(service.UserId,"FindStation","Query : %s",mongo.ToString(queryMap)) buoyStation = &buoyModels.BuoyStation{} err = service.DBAction(Config.Database,"buoy_stations",func(collection *mgo.Collection) error { return collection.Find(queryMap).One(buoyStation) }) if err != nil { tracelog.COMPLETED_ERROR(err,"FindStation") return buoyStation,err } tracelog.COMPLETED(service.UserId,"FindStation") return buoyStation,err } FindStation 用于准备通过 端到端测试我们现在有一个 URL 可以路由到一个控制器以及相应的 business 与 service 层的逻辑,它可以通过以下方式测试: func TestStation(t *testing.T) { r,_ := http.NewRequest("GET","/station/42002",nil) w := httptest.NewRecorder() beego.BeeApp.Handlers.ServeHTTP(w,r) err := struct { Error string }{} json.Unmarshal(w.Body.Bytes(),&err) Convey("Subject: Test Station Endpointn",t,func() { Convey("Status Code Should Be 200",func() { So(w.Code,ShouldEqual,200) }) Convey("The Result Should Not Be Empty",func() { So(w.Body.Len(),ShouldBeGreaterThan,0) }) Convey("The Should Be No Error In The Result",func() { So(len(err.Error),0) }) }) } 测试创建了一个某个路由的虚拟调用。这种做法很赞,因为我们不需要真正地去启动一个 Web 应用来测试代码。使用 goconvey 我们能够创建非常优雅的输出且易于阅读。 以下是一个测试失败的样例: Subject: Test Station Endpoint Status Code Should Be 200 The Result Should Not Be Empty The Should Be No Error In The Result Failures: * /Users/bill/Spaces/Go/Projects/src/github.com/goinggo/beego-mgo/test/endpoints/buoyEndpoints_test.go Line 35: Expected: '200' Actual: '400' (Should be equal) * /Users/bill/Spaces/Go/Projects/src/github.com/goinggo/beego-mgo/test/endpoints/buoyEndpoints_test.go Line 37: Expected: '0' Actual: '9' (Should be equal) 3 assertions thus far --- FAIL: TestStation-8 (0.03 seconds) 以下是一个测试成功的样例: Subject: Test Station Endpoint Status Code Should Be 200 The Result Should Not Be Empty The Should Be No Error In The Result 3 assertions thus far --- PASS: TestStation-8 (0.05 seconds) 结论花点时间下载这个项目随便看看。我尽最大努力让你能够清晰地看到我所想要展示给你的重点。beego 框架让你能够非常轻松地实现抽象和样板代码,遵照 go 的风格集成 go 测试、运行及部署。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |