beego入门文档
你对beego一无所知?没关系,这篇文档会很好的详细介绍beego的各个方面,看这个文档之前首先确认你已经安装了beego,如果你没有安装的话,请看这篇安装指南 导航
最小应用一个最小最简单的应用如下代码所示: package main import ( "github.com/astaxie/beego" ) type MainController struct { beego.Controller } func (this *MainController) Get() { this.Ctx.WriteString("hello world") } func main() { beego.Router("/",&MainController{}) beego.Run() } 把上面的代码保存为hello.go,然后通过命令行进行编译并执行: $ go build main.go $ ./hello 这个时候你可以打开你的浏览器,通过这个地址浏览http://127.0.0.1:8080返回“hello world” 那么上面的代码到底做了些什么呢? 1、首先我们引入了包github.com/astaxie/beego,我们知道Go语言里面引入包会深度优先的去执行引入包的初始化(变量和init函数,更多),beego包中会初始化一个BeeAPP的应用,初始化一些参数。 2、定义Controller,这里我们定义了一个struct为MainController,充分利用了Go语言的组合的概念,匿名包含了beego.Controller,这样我们的MainController就拥有了beego.Controller的所有方法。 3、定义RESTFul方法,通过匿名组合之后,其实目前的MainController已经拥有了Get、Post、Delete、Put等方法,这些方法是分别用来对应用户请求的Method函数,如果用户发起的是POST请求,那么就执行Post函数。所以这里我们定义了MainController的Get方法用来重写继承的Get函数,这样当用户GET请求的时候就会执行该函数。 4、定义main函数,所有的Go应用程序和C语言一样都是Main函数作为入口,所以我们这里定义了我们应用的入口。 5、Router注册路由,路由就是告诉beego,当用户来请求的时候,该如何去调用相应的Controller,这里我们注册了请求/的时候,请求到MainController。这里我们需要知道,Router函数的两个参数函数,第一个是路径,第二个是Controller的指针。 6、Run应用,最后一步就是把在1中初始化的BeeApp开启起来,其实就是内部监听了8080端口:Go默认情况会监听你本机所有的IP上面的8080端口 停止服务的话,请按ctrl+c 新建项目通过如下命令创建beego项目,首先进入gopath目录 bee create hello 这样就建立了一个项目hello,目录结构如下所示 . ├── conf │ └── app.conf ├── controllers │ └── default.go ├── main.go ├── models ├── static │ ├── css │ ├── img │ └── js └── views └── index.tpl 开发模式通过bee创建的项目,beego默认情况下是开发模式。 我们可以通过如下的方式改变我们的模式: beego.RunMode = "pro" 或者我们在conf/app.conf下面设置如下: runmode = pro 以上两种效果一样。 开发模式中
路由设置路由的主要功能是实现从请求地址到实现方法,beego中封装了Controller,所以路由是从路径到ControllerInterface的过程,ControllerInterface的方法有如下: type ControllerInterface interface { Init(ct *Context,cn string) Prepare() Get() Post() Delete() Put() Head() Patch() Options() Finish() Render() error } 这些方法beego.Controller都已经实现了,所以只要用户定义struct的时候匿名包含就可以了。当然更灵活的方法就是用户可以去自定义类似的方法,然后实现自己的逻辑。 用户可以通过如下的方式进行路由设置: beego.Router("/",&controllers.MainController{}) beego.Router("/admin",&admin.UserController{}) beego.Router("/admin/index",&admin.ArticleController{}) beego.Router("/admin/addpkg",&admin.AddController{}) 为了用户更加方便的路由设置,beego参考了sinatra的路由实现,支持多种方式的路由:
静态文件Go语言内部其实已经提供了http.ServeFile,通过这个函数可以实现静态文件的服务。beego针对这个功能进行了一层封装,通过下面的方式进行静态文件注册: beego.SetStaticPath("/static","public")
beego支持多个目录的静态文件注册,用户可以注册如下的静态文件目录: beego.SetStaticPath("/images","images") beego.SetStaticPath("/css","css") beego.SetStaticPath("/js","js") 设置了如上的静态目录之后,用户访问/images/login/login.png,那么就会访问应用对应的目录下面的images/login/login.png文件。如果是访问/static/img/logo.png,那么就访问public/img/logo.png文件。 过滤和中间件beego支持自定义过滤中间件,例如安全验证,强制跳转等 如下例子所示,验证用户名是否是admin,应用于全部的请求: var FilterUser = func(w http.ResponseWriter,r *http.Request) { if r.URL.User == nil || r.URL.User.Username() != "admin" { http.Error(w,"",http.StatusUnauthorized) } } beego.Filter(FilterUser) 还可以通过参数进行过滤,如果匹配参数就执行 beego.Router("/:id([0-9]+)",&admin.EditController{}) beego.FilterParam("id",func(rw http.ResponseWriter,r *http.Request) { dosomething() }) 当然你还可以通过前缀过滤 beego.FilterPrefixPath("/admin",r *http.Request) { dosomething() }) 控制器设计基于beego的Controller设计,只需要匿名组合beego.Controller就可以了,如下所示: type xxxController struct { beego.Controller } beego.Controller实现了接口beego.ControllerInterface,beego.ControllerInterface定义了如下函数:
所以通过子struct的方法重写,用户就可以实现自己的逻辑,接下来我们看一个实际的例子: type AddController struct { beego.Controller } func (this *AddController) Prepare() { } func (this *AddController) Get() { this.Data["content"] ="value" this.Layout = "admin/layout.html" this.TplNames = "admin/add.tpl" } func (this *AddController) Post() { pkgname := this.GetString("pkgname") content := this.GetString("content") pk := models.GetCruPkg(pkgname) if pk.Id == 0 { var pp models.PkgEntity pp.Pid = 0 pp.Pathname = pkgname pp.Intro = pkgname models.InsertPkg(pp) pk = models.GetCruPkg(pkgname) } var at models.Article at.Pkgid = pk.Id at.Content = content models.InsertArticle(at) this.Ctx.Redirect(302,"/admin/index") } 模板处理模板目录beego中默认的模板目录是views,用户可以把你的模板文件放到该目录下,beego会自动在该目录下的所有模板文件进行解析并缓存,开发模式下会每次重新解析,不做缓存。当然用户可以通过如下的方式改变模板的目录: beego.ViewsPath = "/myviewpath" 自动渲染beego中用户无需手动的调用渲染输出模板,beego会自动的在调用玩相应的method方法之后调用Render函数,当然如果你的应用是不需要模板输出的,那么你可以在配置文件或者在main.go中设置关闭自动渲染。 配置文件配置如下: autorender = false main.go文件中设置如下: beego.AutoRender = false 模板数据模板中的数据是通过在Controller中this.Data获取的,所以如果你想在模板中获取内容{{.Content}},那么你需要在Controller中如下设置: this.Data["Context"] = "value" 模板名称beego采用了Go语言内置的模板引擎,所有模板的语法和Go的一模一样,至于如何写模板文件,详细的请参考模板教程。 用户通过在Controller的对应方法中设置相应的模板名称,beego会自动的在viewpath目录下查询该文件并渲染,例如下面的设置,beego会在admin下面找add.tpl文件进行渲染: this.TplNames = "admin/add.tpl" 我们看到上面的模板后缀名是tpl,beego默认情况下支持tpl和html后缀名的模板文件,如果你的后缀名不是这两种,请进行如下设置: beego.AddTemplateExt("你文件的后缀名") 当你设置了自动渲染,然后在你的Controller中没有设置任何的TplNames,那么beego会自动设置你的模板文件如下: c.TplNames = c.ChildName + "/" + c.Ctx.Request.Method + "." + c.TplExt 也就是你对应的Controller名字+请求方法名.模板后缀,也就是如果你的Controller名是AddController,请求方法是POST,默认的文件后缀是tpl,那么就会默认请求/viewpath/AddController/POST.tpl文件。 lauout设计beego支持layout设计,例如你在管理系统中,其实整个的管理界面是固定的,支会变化中间的部分,那么你可以通过如下的设置: this.Layout = "admin/layout.html" this.TplNames = "admin/add.tpl" 在layout.html中你必须设置如下的变量: {{.LayoutContent}} beego就会首先解析TplNames指定的文件,获取内容赋值给LayoutContent,然后最后渲染layout.html文件。 目前采用首先把目录下所有的文件进行缓存,所以用户还可以通过类似这样的方式实现layout: {{template "header.html"}} 处理逻辑 {{template "footer.html"}} 模板函数beego支持用户定义模板函数,但是必须在beego.Run()调用之前,设置如下: func hello(in string)(out string){ out = in + "world" return } beego.AddFuncMap("hi",hello) 定义之后你就可以在模板中这样使用了: {{.Content | hi}} 目前beego内置的模板函数有如下:
request处理我们经常需要获取用户传递的数据,包括Get、POST等方式的请求,beego里面会自动解析这些数据,你可以通过如下方式获取数据
使用例子如下: func (this *MainController) Post() { jsoninfo := this.GetString("jsoninfo") if jsoninfo == "" { this.Ctx.WriteString("jsoninfo is empty") return } } 如果你需要的数据可能是其他类型的,例如是int类型而不是int64,那么你需要这样处理: func (this *MainController) Post() { id := this.Input().Get("id") intid,err := strconv.Atoi(id) } 更多其他的request的信息,用户可以通过this.Ctx.Request获取信息,关于该对象的属性和方法参考手册Request 文件上传在beego中你可以很容易的处理文件上传,就是别忘记在你的form表单中增加这个属性enctype="multipart/form-data",否者你的浏览器不会传输你的上传文件。 文件上传之后一般是放在系统的内存里面,如果文件的size大于设置的缓存内存大小,那么就放在临时文件中,默认的缓存内存是64M,你可以通过如下来调整这个缓存内存大小: beego.MaxMemory = 1<<22 或者在配置文件中通过如下设置 maxmemory = 1<<22 beego提供了两个很方便的方法来处理文件上传:
保存的代码例子如下: func (this *MainController) Post() { this.SaveToFile("the_file","/var/www/uploads/uploaded_file.txt"") } JSON和XML输出beego当初设计的时候就考虑了API功能的设计,而我们在设计API的时候经常是输出JSON或者XML数据,那么beego提供了这样的方式直接输出: JSON数据直接输出,设置content-type为application/json: func (this *AddController) Get() { mystruct := { ... } this.Data["json"] = &mystruct this.ServeJson() } XML数据直接输出,设置content-type为application/xml: func (this *AddController) Get() { mystruct := { ... } this.Data["xml"]=&mystruct this.ServeXml() } 跳转和错误我们在做Web开发的时候,经常会遇到页面调整和错误处理,beego这这方面也进行了考虑,通过Redirect方法来进行跳转: func (this *AddController) Get() { this.Redirect("/",302) } @todo 错误处理还需要后期改进 response处理response可能会有集中情况:
Sessionsbeego内置了session模块,目前session模块支持的后端引擎包括memory、file、mysql、redis四中,用户也可以根据相应的interface实现自己的引擎。 beego中使用session相当方便,只要在main入口函数中设置如下: beego.SessionOn = true 或者通过配置文件配置如下: sessionon = true 通过这种方式就可以开启session,如何使用session,请看下面的例子: func (this *MainController) Get() { v := this.GetSession("asta") if v == nil { this.SetSession("asta",int(1)) this.Data["num"] = 0 } else { this.SetSession("asta",v.(int)+1) this.Data["num"] = v.(int) } this.TplNames = "index.tpl" } 上面的例子中我们知道session有几个方便的方法:
session操作主要有设置session、获取session、删除session 当然你要可以通过下面的方式自己控制相应的逻辑这些逻辑: sess:=this.StartSession() defer sess.SessionRelease() sess对象具有如下方法:
但是我还是建议大家采用SetSession、GetSession、DelSession三个方法来操作,避免自己在操作的过程中资源没释放的问题。 关于Session模块使用中的一些参数设置:
当SessionProvider为file时,SessionSavePath是只保存文件的目录,如下所示: beego.SessionProvider = "file" beego.SessionSavePath = "./tmp" 当SessionProvider为mysql时,SessionSavePath是链接地址,采用go-sql-driver,如下所示: beego.SessionProvider = "mysql" beego.SessionSavePath = "username:password@protocol(address)/dbname?param=value" 当SessionProvider为redis时,SessionSavePath是redis的链接地址,采用了redigo,如下所示: beego.SessionProvider = "redis" beego.SessionSavePath = "127.0.0.1:6379" Cache设置beego内置了一个cache模块,实现了类似memcache的功能,缓存数据在内存中,主要的使用方法如下: var ( urllist *beego.BeeCache ) func init() { urllist = beego.NewBeeCache() urllist.Every = 0 //不过期 urllist.Start() } func (this *ShortController) Post() { var result ShortResult longurl := this.Input().Get("longurl") beego.Info(longurl) result.UrlLong = longurl urlmd5 := models.GetMD5(longurl) beego.Info(urlmd5) if urllist.IsExist(urlmd5) { result.UrlShort = urllist.Get(urlmd5).(string) } else { result.UrlShort = models.Generate() err := urllist.Put(urlmd5,result.UrlShort,0) if err != nil { beego.Info(err) } err = urllist.Put(result.UrlShort,longurl,0) if err != nil { beego.Info(err) } } this.Data["json"] = result this.ServeJson() } 上面这个例子演示了如何使用beego的Cache模块,主要是通过beego.NewBeeCache初始化一个对象,然后设置过期时间,开启过期检测,在业务逻辑中就可以通过如下的接口进行增删改的操作:
安全的Map我们知道在Go语言里面map是非线程安全的,详细的atomic_maps。但是我们在平常的业务中经常需要用到线程安全的map,特别是在goroutine的情况下,所以beego内置了一个简单的线程安全的map: bm := NewBeeMap() if !bm.Set("astaxie",1) { t.Error("set Error") } if !bm.Check("astaxie") { t.Error("check err") } if v := bm.Get("astaxie"); v.(int) != 1 { t.Error("get err") } bm.Delete("astaxie") if bm.Check("astaxie") { t.Error("delete err") } 上面演示了如何使用线程安全的Map,主要的接口有:
日志处理beego默认有一个初始化的BeeLogger对象输出内容到stdout中,你可以通过如下的方式设置自己的输出: beego.SetLogger(*log.Logger) 只要你的输出符合*log.Logger就可以,例如输出到文件: fd,err := os.OpenFile("/var/log/beeapp/beeapp.log",os.O_RDWR|os.O_APPEND,0644) if err != nil { beego.Critical("openfile beeapp.log:",err) return } lg := log.New(fd,log.Ldate|log.Ltime) beego.SetLogger(lg) 不同级别的log日志函数
你可以通过下面的方式设置不同的日志分级: beego.SetLevel(beego.LevelError) 当你代码中有很多日志输出之后,如果想上线,但是你不想输出Trace、Debug、Info等信息,那么你可以设置如下: beego.SetLevel(beego.LevelWarning) 这样的话就不会输出小于这个level的日志,日志的排序如下: LevelTrace、LevelDebug、LevelInfo、LevelWarning、 LevelError、LevelCritical 用户可以根据不同的级别输出不同的错误信息,如下例子所示: Examples of log messages
Examplefunc internalCalculationFunc(x,y int) (result int,err error) { beego.Debug("calculating z. x:",x," y:",y) z := y switch { case x == 3 : beego.Trace("x == 3") panic("Failure.") case y == 1 : beego.Trace("y == 1") return 0,errors.New("Error!") case y == 2 : beego.Trace("y == 2") z = x default : beego.Trace("default") z += x } retVal := z-3 beego.Debug("Returning ",retVal) return retVal,nil } func processInput(input inputData) { defer func() { if r := recover(); r != nil { beego.Error("Unexpected error occurred: ",r) outputs <- outputData{result : 0,error : true} } }() beego.Info("Received input signal. x:",input.x,input.y) res,err := internalCalculationFunc(input.x,input.y) if err != nil { beego.Warn("Error in calculation:",err.Error()) } beego.Info("Returning result: ",res," error: ",err) outputs <- outputData{result : res,error : err != nil} } func main() { inputs = make(chan inputData) outputs = make(chan outputData) criticalChan = make(chan int) beego.Info("App started.") go consumeResults(outputs) beego.Info("Started receiving results.") go generateInputs(inputs) beego.Info("Started sending signals.") for { select { case input := <- inputs: processInput(input) case <- criticalChan: beego.Critical("Caught value from criticalChan: Go shut down.") panic("Shut down due to critical fault.") } } } 配置管理beego支持解析ini文件,beego默认会解析当前应用下的conf/app.conf文件 通过这个文件你可以初始化很多beego的默认参数 appname = beepkg httpaddr = "127.0.0.1" httpport = 9090 runmode ="dev" autorender = false autorecover = false viewspath = "myview" 上面这些参数会替换beego默认的一些参数。 你可以在配置文件中配置应用需要用的一些配置信息,例如下面所示的数据库信息: mysqluser = "root" mysqlpass = "rootpass" mysqlurls = "127.0.0.1" mysqldb = "beego" 那么你就可以通过如下的方式获取设置的配置信息: beego.AppConfig.String("mysqluser") beego.AppConfig.String("mysqlpass") beego.AppConfig.String("mysqlurls") beego.AppConfig.String("mysqldb") AppConfig支持如下方法
系统默认参数beego中带有很多可配置的参数,我们来一一认识一下它们,这样有利于我们在接下来的beego开发中可以充分的发挥他们的作用:
第三方应用集成beego支持第三方应用的集成,用户可以自定义http.Handler,用户可以通过如下方式进行注册路由: beego.RouterHandler("/chat/:info(.*)",sockjshandler) sockjshandler实现了接口http.Handler。 目前在beego的example中有支持sockjs的chat例子,示例代码如下: package main import ( "fmt" "github.com/astaxie/beego" "github.com/fzzy/sockjs-go/sockjs" "strings" ) var users *sockjs.SessionPool = sockjs.NewSessionPool() func chatHandler(s sockjs.Session) { users.Add(s) defer users.Remove(s) for { m := s.Receive() if m == nil { break } fullAddr := s.Info().RemoteAddr addr := fullAddr[:strings.LastIndex(fullAddr,":")] m = []byte(fmt.Sprintf("%s: %s",addr,m)) users.Broadcast(m) } } type MainController struct { beego.Controller } func (m *MainController) Get() { m.TplNames = "index.html" } func main() { conf := sockjs.NewConfig() sockjshandler := sockjs.NewHandler("/chat",chatHandler,conf) beego.Router("/",&MainController{}) beego.RouterHandler("/chat/:info(.*)",sockjshandler) beego.Run() } 通过上面的代码很简单的实现了一个多人的聊天室。上面这个只是一个sockjs的例子,我想通过大家自定义http.Handler,可以有很多种方式来进行扩展beego应用。 部署编译应用Go语言的应用最后编译之后是一个二进制文件,你只需要copy这个应用到服务器上,运行起来就行。beego由于带有几个静态文件、配置文件、模板文件三个目录,所以用户部署的时候需要同时copy这三个目录到相应的部署应用之下,下面以我实际的应用部署为例: $ mkdir /opt/app/beepkg $ cp beepkg /opt/app/beepkg $ cp -fr views /opt/app/beepkg $ cp -fr static /opt/app/beepkg $ cp -fr conf /opt/app/beepkg 这样在/opt/app/beepkg目录下面就会显示如下的目录结构: . ├── conf │ ├── app.conf ├── static │ ├── css │ ├── img │ └── js └── views └── index.tpl ├── beepkg 这样我们就已经把我们需要的应用搬到服务器了,那么接下来就可以开始部署了,我现在服务器端用两种方式来run,
个人比较推荐第一种方式,可以很好的管理起来应用 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |