beego入门文档
beego入門文檔
轉(zhuǎn)自:https://my.oschina.net/astaxie/blog/124040你對(duì)beego一無所知?沒關(guān)系,這篇文檔會(huì)很好的詳細(xì)介紹beego的各個(gè)方面,看這個(gè)文檔之前首先確認(rèn)你已經(jīng)安裝了beego,如果你沒有安裝的話,請(qǐng)看這篇安裝指南
導(dǎo)航
- 最小應(yīng)用
- 新建項(xiàng)目
- 開發(fā)模式
- 路由設(shè)置
- 靜態(tài)文件
- 過濾和中間件
- Controller設(shè)計(jì)
- 模板處理
- request處理
- 跳轉(zhuǎn)和錯(cuò)誤
- response處理
- Sessions
- Cache設(shè)置
- 安全的Map
- 日志處理
- 配置管理
- beego參數(shù)
- 第三方應(yīng)用集成
- 部署編譯應(yīng)用
最小應(yīng)用
一個(gè)最小最簡單的應(yīng)用如下代碼所示:
package mainimport ("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,然后通過命令行進(jìn)行編譯并執(zhí)行:
$ go build main.go $ ./hello這個(gè)時(shí)候你可以打開你的瀏覽器,通過這個(gè)地址瀏覽http://127.0.0.1:8080返回“hello world”
那么上面的代碼到底做了些什么呢?
1、首先我們引入了包github.com/astaxie/beego,我們知道Go語言里面引入包會(huì)深度優(yōu)先的去執(zhí)行引入包的初始化(變量和init函數(shù),更多),beego包中會(huì)初始化一個(gè)BeeAPP的應(yīng)用,初始化一些參數(shù)。
2、定義Controller,這里我們定義了一個(gè)struct為MainController,充分利用了Go語言的組合的概念,匿名包含了beego.Controller,這樣我們的MainController就擁有了beego.Controller的所有方法。
3、定義RESTFul方法,通過匿名組合之后,其實(shí)目前的MainController已經(jīng)擁有了Get、Post、Delete、Put等方法,這些方法是分別用來對(duì)應(yīng)用戶請(qǐng)求的Method函數(shù),如果用戶發(fā)起的是POST請(qǐng)求,那么就執(zhí)行Post函數(shù)。所以這里我們定義了MainController的Get方法用來重寫繼承的Get函數(shù),這樣當(dāng)用戶GET請(qǐng)求的時(shí)候就會(huì)執(zhí)行該函數(shù)。
4、定義main函數(shù),所有的Go應(yīng)用程序和C語言一樣都是Main函數(shù)作為入口,所以我們這里定義了我們應(yīng)用的入口。
5、Router注冊(cè)路由,路由就是告訴beego,當(dāng)用戶來請(qǐng)求的時(shí)候,該如何去調(diào)用相應(yīng)的Controller,這里我們注冊(cè)了請(qǐng)求/的時(shí)候,請(qǐng)求到MainController。這里我們需要知道,Router函數(shù)的兩個(gè)參數(shù)函數(shù),第一個(gè)是路徑,第二個(gè)是Controller的指針。
6、Run應(yīng)用,最后一步就是把在1中初始化的BeeApp開啟起來,其實(shí)就是內(nèi)部監(jiān)聽了8080端口:Go默認(rèn)情況會(huì)監(jiān)聽你本機(jī)所有的IP上面的8080端口
停止服務(wù)的話,請(qǐng)按ctrl+c
新建項(xiàng)目
通過如下命令創(chuàng)建beego項(xiàng)目,首先進(jìn)入gopath目錄
bee create hello這樣就建立了一個(gè)項(xiàng)目hello,目錄結(jié)構(gòu)如下所示
. ├── conf │ └── app.conf ├── controllers │ └── default.go ├── main.go ├── models ├── static │ ├── css │ ├── img │ └── js └── views└── index.tpl開發(fā)模式
通過bee創(chuàng)建的項(xiàng)目,beego默認(rèn)情況下是開發(fā)模式。
我們可以通過如下的方式改變我們的模式:
beego.RunMode = "pro"或者我們?cè)赾onf/app.conf下面設(shè)置如下:
runmode = pro以上兩種效果一樣。
開發(fā)模式中
-
開發(fā)模式下,如果你的目錄不存在views目錄,那么會(huì)出現(xiàn)類似下面的錯(cuò)誤提示:
2013/04/13 19:36:17 [W] [stat views: no such file or directory] -
模板會(huì)自動(dòng)重新加載不緩存。
-
如果服務(wù)端出錯(cuò),那么就會(huì)在瀏覽器端顯示如下類似的截圖:
路由設(shè)置
路由的主要功能是實(shí)現(xiàn)從請(qǐng)求地址到實(shí)現(xiàn)方法,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都已經(jīng)實(shí)現(xiàn)了,所以只要用戶定義struct的時(shí)候匿名包含就可以了。當(dāng)然更靈活的方法就是用戶可以去自定義類似的方法,然后實(shí)現(xiàn)自己的邏輯。
用戶可以通過如下的方式進(jìn)行路由設(shè)置:
beego.Router("/", &controllers.MainController{}) beego.Router("/admin", &admin.UserController{}) beego.Router("/admin/index", &admin.ArticleController{}) beego.Router("/admin/addpkg", &admin.AddController{})為了用戶更加方便的路由設(shè)置,beego參考了sinatra的路由實(shí)現(xiàn),支持多種方式的路由:
-
beego.Router("/api/:id([0-9]+)", &controllers.RController{})
自定義正則匹配 //匹配 /api/123 :id= 123 -
beego.Router("/news/:all", &controllers.RController{})
全匹配方式 //匹配 /news/path/to/123.html :all= path/to/123.html -
beego.Router("/user/:username([\w]+)", &controllers.RController{})
正則字符串匹配 //匹配 /user/astaxie :username = astaxie -
beego.Router("/download/*.*", &controllers.RController{})
*匹配方式 //匹配 /download/file/api.xml :path= file/api :ext=xml -
beego.Router("/download/ceshi/*", &controllers.RController{})
*全匹配方式 //匹配 /download/ceshi/file/api.json :splat=file/api.json -
beego.Router("/int", &controllers.RController{})
int類型設(shè)置方式 //匹配 :id為int類型,框架幫你實(shí)現(xiàn)了正則([0-9]+) -
beego.Router("/:hi:string", &controllers.RController{})
string類型設(shè)置方式 //匹配 :hi為string類型??蚣軒湍銓?shí)現(xiàn)了正則([\w]+)
靜態(tài)文件
Go語言內(nèi)部其實(shí)已經(jīng)提供了http.ServeFile,通過這個(gè)函數(shù)可以實(shí)現(xiàn)靜態(tài)文件的服務(wù)。beego針對(duì)這個(gè)功能進(jìn)行了一層封裝,通過下面的方式進(jìn)行靜態(tài)文件注冊(cè):
beego.SetStaticPath("/static","public")- 第一個(gè)參數(shù)是路徑,url路徑信息
- 第二個(gè)參數(shù)是靜態(tài)文件目錄(相對(duì)應(yīng)用所在的目錄)
beego支持多個(gè)目錄的靜態(tài)文件注冊(cè),用戶可以注冊(cè)如下的靜態(tài)文件目錄:
beego.SetStaticPath("/images","images") beego.SetStaticPath("/css","css") beego.SetStaticPath("/js","js")設(shè)置了如上的靜態(tài)目錄之后,用戶訪問/images/login/login.png,那么就會(huì)訪問應(yīng)用對(duì)應(yīng)的目錄下面的images/login/login.png文件。如果是訪問/static/img/logo.png,那么就訪問public/img/logo.png文件。
過濾和中間件
beego支持自定義過濾中間件,例如安全驗(yàn)證,強(qiáng)制跳轉(zhuǎn)等
如下例子所示,驗(yàn)證用戶名是否是admin,應(yīng)用于全部的請(qǐng)求:
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)還可以通過參數(shù)進(jìn)行過濾,如果匹配參數(shù)就執(zhí)行
beego.Router("/:id([0-9]+)", &admin.EditController{}) beego.FilterParam("id", func(rw http.ResponseWriter, r *http.Request) {dosomething() })當(dāng)然你還可以通過前綴過濾
beego.FilterPrefixPath("/admin", func(rw http.ResponseWriter, r *http.Request) {dosomething() })控制器設(shè)計(jì)
基于beego的Controller設(shè)計(jì),只需要匿名組合beego.Controller就可以了,如下所示:
type xxxController struct {beego.Controller }beego.Controller實(shí)現(xiàn)了接口beego.ControllerInterface,beego.ControllerInterface定義了如下函數(shù):
-
Init(ct *Context, cn string)
這個(gè)函數(shù)主要初始化了Context、相應(yīng)的Controller名稱,模板名,初始化模板參數(shù)的容器Data
-
Prepare()
這個(gè)函數(shù)主要是為了用戶擴(kuò)展用的,這個(gè)函數(shù)會(huì)在下面定義的這些Method方法之前執(zhí)行,用戶可以重寫這個(gè)函數(shù)實(shí)現(xiàn)類似用戶驗(yàn)證之類。
-
Get()
如果用戶請(qǐng)求的HTTP Method是GET, 那么就執(zhí)行該函數(shù),默認(rèn)是403,用戶繼承的子struct中可以實(shí)現(xiàn)了該方法以處理Get請(qǐng)求.
-
Post()
如果用戶請(qǐng)求的HTTP Method是POST, 那么就執(zhí)行該函數(shù),默認(rèn)是403,用戶繼承的子struct中可以實(shí)現(xiàn)了該方法以處理Post請(qǐng)求.
-
Delete()
如果用戶請(qǐng)求的HTTP Method是DELETE, 那么就執(zhí)行該函數(shù),默認(rèn)是403,用戶繼承的子struct中可以實(shí)現(xiàn)了該方法以處理Delete請(qǐng)求.
-
Put()
如果用戶請(qǐng)求的HTTP Method是PUT, 那么就執(zhí)行該函數(shù),默認(rèn)是403,用戶繼承的子struct中可以實(shí)現(xiàn)了該方法以處理Put請(qǐng)求.
-
Head()
如果用戶請(qǐng)求的HTTP Method是HEAD, 那么就執(zhí)行該函數(shù),默認(rèn)是403,用戶繼承的子struct中可以實(shí)現(xiàn)了該方法以處理Head請(qǐng)求.
-
Patch()
如果用戶請(qǐng)求的HTTP Method是PATCH, 那么就執(zhí)行該函數(shù),默認(rèn)是403,用戶繼承的子struct中可以實(shí)現(xiàn)了該方法以處理Patch請(qǐng)求.
-
Options()
如果用戶請(qǐng)求的HTTP Method是OPTIONS, 那么就執(zhí)行該函數(shù),默認(rèn)是403,用戶繼承的子struct中可以實(shí)現(xiàn)了該方法以處理Options請(qǐng)求.
-
Finish()
這個(gè)函數(shù)實(shí)在執(zhí)行完相應(yīng)的http Method方法之后執(zhí)行的,默認(rèn)是空,用戶可以在子Strcut中重寫這個(gè)函數(shù),執(zhí)行例如數(shù)據(jù)庫關(guān)閉,清理數(shù)據(jù)之類的工作
-
Render() error
這個(gè)函數(shù)主要用來實(shí)現(xiàn)渲染模板,如果beego.AutoRender為true的情況下才會(huì)執(zhí)行。
所以通過子struct的方法重寫,用戶就可以實(shí)現(xiàn)自己的邏輯,接下來我們看一個(gè)實(shí)際的例子:
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.PkgEntitypp.Pid = 0pp.Pathname = pkgnamepp.Intro = pkgnamemodels.InsertPkg(pp)pk = models.GetCruPkg(pkgname)}var at models.Articleat.Pkgid = pk.Idat.Content = contentmodels.InsertArticle(at)this.Ctx.Redirect(302, "/admin/index") }模板處理
模板目錄
beego中默認(rèn)的模板目錄是views,用戶可以把你的模板文件放到該目錄下,beego會(huì)自動(dòng)在該目錄下的所有模板文件進(jìn)行解析并緩存,開發(fā)模式下會(huì)每次重新解析,不做緩存。當(dāng)然用戶可以通過如下的方式改變模板的目錄:
beego.ViewsPath = "/myviewpath"自動(dòng)渲染
beego中用戶無需手動(dòng)的調(diào)用渲染輸出模板,beego會(huì)自動(dòng)的在調(diào)用玩相應(yīng)的method方法之后調(diào)用Render函數(shù),當(dāng)然如果你的應(yīng)用是不需要模板輸出的,那么你可以在配置文件或者在main.go中設(shè)置關(guān)閉自動(dòng)渲染。
配置文件配置如下:
autorender = falsemain.go文件中設(shè)置如下:
beego.AutoRender = false模板數(shù)據(jù)
模板中的數(shù)據(jù)是通過在Controller中this.Data獲取的,所以如果你想在模板中獲取內(nèi)容{{.Content}},那么你需要在Controller中如下設(shè)置:
this.Data["Context"] = "value"模板名稱
beego采用了Go語言內(nèi)置的模板引擎,所有模板的語法和Go的一模一樣,至于如何寫模板文件,詳細(xì)的請(qǐng)參考模板教程。
用戶通過在Controller的對(duì)應(yīng)方法中設(shè)置相應(yīng)的模板名稱,beego會(huì)自動(dòng)的在viewpath目錄下查詢?cè)撐募秩?#xff0c;例如下面的設(shè)置,beego會(huì)在admin下面找add.tpl文件進(jìn)行渲染:
this.TplNames = "admin/add.tpl"我們看到上面的模板后綴名是tpl,beego默認(rèn)情況下支持tpl和html后綴名的模板文件,如果你的后綴名不是這兩種,請(qǐng)進(jìn)行如下設(shè)置:
beego.AddTemplateExt("你文件的后綴名")當(dāng)你設(shè)置了自動(dòng)渲染,然后在你的Controller中沒有設(shè)置任何的TplNames,那么beego會(huì)自動(dòng)設(shè)置你的模板文件如下:
c.TplNames = c.ChildName + "/" + c.Ctx.Request.Method + "." + c.TplExt也就是你對(duì)應(yīng)的Controller名字+請(qǐng)求方法名.模板后綴,也就是如果你的Controller名是AddController,請(qǐng)求方法是POST,默認(rèn)的文件后綴是tpl,那么就會(huì)默認(rèn)請(qǐng)求/viewpath/AddController/POST.tpl文件。
lauout設(shè)計(jì)
beego支持layout設(shè)計(jì),例如你在管理系統(tǒng)中,其實(shí)整個(gè)的管理界面是固定的,支會(huì)變化中間的部分,那么你可以通過如下的設(shè)置:
this.Layout = "admin/layout.html" this.TplNames = "admin/add.tpl"在layout.html中你必須設(shè)置如下的變量:
{{.LayoutContent}}beego就會(huì)首先解析TplNames指定的文件,獲取內(nèi)容賦值給LayoutContent,然后最后渲染layout.html文件。
目前采用首先把目錄下所有的文件進(jìn)行緩存,所以用戶還可以通過類似這樣的方式實(shí)現(xiàn)layout:
{{template "header.html"}} 處理邏輯 {{template "footer.html"}}模板函數(shù)
beego支持用戶定義模板函數(shù),但是必須在beego.Run()調(diào)用之前,設(shè)置如下:
func hello(in string)(out string){out = in + "world"return }beego.AddFuncMap("hi",hello)定義之后你就可以在模板中這樣使用了:
{{.Content | hi}}目前beego內(nèi)置的模板函數(shù)有如下:
-
markdown
實(shí)現(xiàn)了把markdown文本轉(zhuǎn)化為html信息,使用方法{{markdown .Content}}
-
dateformat
實(shí)現(xiàn)了時(shí)間的格式化,返回字符串,使用方法{{dateformat .Time "2006-01-02T15:04:05Z07:00"}}
-
date
實(shí)現(xiàn)了類似PHP的date函數(shù),可以很方便的根據(jù)字符串返回時(shí)間,使用方法{{date .T "Y-m-d H:i:s"}}
-
compare
實(shí)現(xiàn)了比較兩個(gè)對(duì)象的比較,如果相同返回true,否者false,使用方法{{compare .A .B}}
-
substr
實(shí)現(xiàn)了字符串的截取,支持中文截取的完美截取,使用方法{{substr .Str 0 30}}
-
html2str
實(shí)現(xiàn)了把html轉(zhuǎn)化為字符串,剔除一些script、css之類的元素,返回純文本信息,使用方法{{html2str .Htmlinfo}}
-
str2html
實(shí)現(xiàn)了把相應(yīng)的字符串當(dāng)作HTML來輸出,不轉(zhuǎn)義,使用方法{{str2html .Strhtml}}
-
htmlquote
實(shí)現(xiàn)了基本的html字符轉(zhuǎn)義,使用方法{{htmlquote .quote}}
-
htmlunquote
實(shí)現(xiàn)了基本的反轉(zhuǎn)移字符,使用方法{{htmlunquote .unquote}}
request處理
我們經(jīng)常需要獲取用戶傳遞的數(shù)據(jù),包括Get、POST等方式的請(qǐng)求,beego里面會(huì)自動(dòng)解析這些數(shù)據(jù),你可以通過如下方式獲取數(shù)據(jù)
- GetString(key string) string
- GetInt(key string) (int64, error)
- GetBool(key string) (bool, error)
使用例子如下:
func (this *MainController) Post() {jsoninfo := this.GetString("jsoninfo")if jsoninfo == "" {this.Ctx.WriteString("jsoninfo is empty")return} }如果你需要的數(shù)據(jù)可能是其他類型的,例如是int類型而不是int64,那么你需要這樣處理:
func (this *MainController) Post() {id := this.Input().Get("id")intid, err := strconv.Atoi(id) }更多其他的request的信息,用戶可以通過this.Ctx.Request獲取信息,關(guān)于該對(duì)象的屬性和方法參考手冊(cè)Request
文件上傳
在beego中你可以很容易的處理文件上傳,就是別忘記在你的form表單中增加這個(gè)屬性enctype="multipart/form-data",否者你的瀏覽器不會(huì)傳輸你的上傳文件。
文件上傳之后一般是放在系統(tǒng)的內(nèi)存里面,如果文件的size大于設(shè)置的緩存內(nèi)存大小,那么就放在臨時(shí)文件中,默認(rèn)的緩存內(nèi)存是64M,你可以通過如下來調(diào)整這個(gè)緩存內(nèi)存大小:
beego.MaxMemory = 1<<22或者在配置文件中通過如下設(shè)置
maxmemory = 1<<22beego提供了兩個(gè)很方便的方法來處理文件上傳:
-
GetFile(key string) (multipart.File, *multipart.FileHeader, error)
該方法主要用于用戶讀取表單中的文件名the_file,然后返回相應(yīng)的信息,用戶根據(jù)這些變量來處理文件上傳:過濾、保存文件等。
-
SaveToFile(fromfile, tofile string) error
該方法是在GetFile的基礎(chǔ)上實(shí)現(xiàn)了快速保存的功能
保存的代碼例子如下:
func (this *MainController) Post() {this.SaveToFile("the_file","/var/www/uploads/uploaded_file.txt"") }JSON和XML輸出
beego當(dāng)初設(shè)計(jì)的時(shí)候就考慮了API功能的設(shè)計(jì),而我們?cè)谠O(shè)計(jì)API的時(shí)候經(jīng)常是輸出JSON或者XML數(shù)據(jù),那么beego提供了這樣的方式直接輸出:
JSON數(shù)據(jù)直接輸出,設(shè)置content-type為application/json:
func (this *AddController) Get() {mystruct := { ... }this.Data["json"] = &mystructthis.ServeJson() }XML數(shù)據(jù)直接輸出,設(shè)置content-type為application/xml:
func (this *AddController) Get() {mystruct := { ... }this.Data["xml"]=&mystructthis.ServeXml() }跳轉(zhuǎn)和錯(cuò)誤
我們?cè)谧鯳eb開發(fā)的時(shí)候,經(jīng)常會(huì)遇到頁面調(diào)整和錯(cuò)誤處理,beego這這方面也進(jìn)行了考慮,通過Redirect方法來進(jìn)行跳轉(zhuǎn):
func (this *AddController) Get() {this.Redirect("/", 302) }@todo?錯(cuò)誤處理還需要后期改進(jìn)
response處理
response可能會(huì)有集中情況:
模板輸出
模板輸出上面模板介紹里面已經(jīng)介紹,beego會(huì)在執(zhí)行完相應(yīng)的Controller里面的對(duì)應(yīng)的Method之后輸出到模板。
跳轉(zhuǎn)
上一節(jié)介紹的跳轉(zhuǎn)就是我們經(jīng)常用到的頁面之間的跳轉(zhuǎn)
字符串輸出
有些時(shí)候我們只是想輸出相應(yīng)的一個(gè)字符串,那么我們可以通過如下的代碼實(shí)現(xiàn)
this.Ctx.WriteString("ok")Sessions
beego內(nèi)置了session模塊,目前session模塊支持的后端引擎包括memory、file、mysql、redis四中,用戶也可以根據(jù)相應(yīng)的interface實(shí)現(xiàn)自己的引擎。
beego中使用session相當(dāng)方便,只要在main入口函數(shù)中設(shè)置如下:
beego.SessionOn = true或者通過配置文件配置如下:
sessionon = true通過這種方式就可以開啟session,如何使用session,請(qǐng)看下面的例子:
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有幾個(gè)方便的方法:
- SetSession(name string, value interface{})
- GetSession(name string) interface{}
- DelSession(name string)
session操作主要有設(shè)置session、獲取session、刪除session
當(dāng)然你要可以通過下面的方式自己控制相應(yīng)的邏輯這些邏輯:
sess:=this.StartSession() defer sess.SessionRelease()sess對(duì)象具有如下方法:
- sess.Set()
- sess.Get()
- sess.Delete()
- sess.SessionID()
但是我還是建議大家采用SetSession、GetSession、DelSession三個(gè)方法來操作,避免自己在操作的過程中資源沒釋放的問題。
關(guān)于Session模塊使用中的一些參數(shù)設(shè)置:
-
SessionOn
設(shè)置是否開啟Session,默認(rèn)是false,配置文件對(duì)應(yīng)的參數(shù)名:sessionon
-
SessionProvider
設(shè)置Session的引擎,默認(rèn)是memory,目前支持還有file、mysql、redis等,配置文件對(duì)應(yīng)的參數(shù)名:sessionprovider
-
SessionName
設(shè)置cookies的名字,Session默認(rèn)是保存在用戶的瀏覽器cookies里面的,默認(rèn)名是beegosessionID,配置文件對(duì)應(yīng)的參數(shù)名是:sessionname
-
SessionGCMaxLifetime
設(shè)置Session過期的時(shí)間,默認(rèn)值是3600秒,配置文件對(duì)應(yīng)的參數(shù):sessiongcmaxlifetime
-
SessionSavePath
設(shè)置對(duì)應(yīng)file、mysql、redis引擎的保存路徑或者鏈接地址,默認(rèn)值是空,配置文件對(duì)應(yīng)的參數(shù):sessionsavepath
當(dāng)SessionProvider為file時(shí),SessionSavePath是只保存文件的目錄,如下所示:
beego.SessionProvider = "file" beego.SessionSavePath = "./tmp"當(dāng)SessionProvider為mysql時(shí),SessionSavePath是鏈接地址,采用go-sql-driver,如下所示:
beego.SessionProvider = "mysql" beego.SessionSavePath = "username:password@protocol(address)/dbname?param=value"當(dāng)SessionProvider為redis時(shí),SessionSavePath是redis的鏈接地址,采用了redigo,如下所示:
beego.SessionProvider = "redis" beego.SessionSavePath = "127.0.0.1:6379"Cache設(shè)置
beego內(nèi)置了一個(gè)cache模塊,實(shí)現(xiàn)了類似memcache的功能,緩存數(shù)據(jù)在內(nèi)存中,主要的使用方法如下:
var (urllist *beego.BeeCache )func init() {urllist = beego.NewBeeCache()urllist.Every = 0 //不過期urllist.Start() }func (this *ShortController) Post() {var result ShortResultlongurl := this.Input().Get("longurl")beego.Info(longurl)result.UrlLong = longurlurlmd5 := 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"] = resultthis.ServeJson() }上面這個(gè)例子演示了如何使用beego的Cache模塊,主要是通過beego.NewBeeCache初始化一個(gè)對(duì)象,然后設(shè)置過期時(shí)間,開啟過期檢測(cè),在業(yè)務(wù)邏輯中就可以通過如下的接口進(jìn)行增刪改的操作:
- Get(name string) interface{}
- Put(name string, value interface{}, expired int) error
- Delete(name string) (ok bool, err error)
- IsExist(name string) bool
安全的Map
我們知道在Go語言里面map是非線程安全的,詳細(xì)的atomic_maps。但是我們?cè)谄匠5臉I(yè)務(wù)中經(jīng)常需要用到線程安全的map,特別是在goroutine的情況下,所以beego內(nèi)置了一個(gè)簡單的線程安全的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,主要的接口有:
- Get(k interface{}) interface{}
- Set(k interface{}, v interface{}) bool
- Check(k interface{}) bool
- Delete(k interface{})
日志處理
beego默認(rèn)有一個(gè)初始化的BeeLogger對(duì)象輸出內(nèi)容到stdout中,你可以通過如下的方式設(shè)置自己的輸出:
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)不同級(jí)別的log日志函數(shù)
- Trace(v ...interface{})
- Debug(v ...interface{})
- Info(v ...interface{})
- Warn(v ...interface{})
- Error(v ...interface{})
- Critical(v ...interface{})
你可以通過下面的方式設(shè)置不同的日志分級(jí):
beego.SetLevel(beego.LevelError)當(dāng)你代碼中有很多日志輸出之后,如果想上線,但是你不想輸出Trace、Debug、Info等信息,那么你可以設(shè)置如下:
beego.SetLevel(beego.LevelWarning)這樣的話就不會(huì)輸出小于這個(gè)level的日志,日志的排序如下:
LevelTrace、LevelDebug、LevelInfo、LevelWarning、 LevelError、LevelCritical
用戶可以根據(jù)不同的級(jí)別輸出不同的錯(cuò)誤信息,如下例子所示:
Examples of log messages
-
Trace
- "Entered parse function validation block"
- "Validation: entered second 'if'"
- "Dictionary 'Dict' is empty. Using default value"
-
Debug
- "Web page requested:?http://somesite.com?Params='...'"
- "Response generated. Response size: 10000. Sending."
- "New file received. Type:PNG Size:20000"
-
Info
- "Web server restarted"
- "Hourly statistics: Requested pages: 12345 Errors: 123 ..."
- "Service paused. Waiting for 'resume' call"
-
Warn
- "Cache corrupted for file='test.file'. Reading from back-end"
- "Database 192.168.0.7/DB not responding. Using backup 192.168.0.8/DB"
- "No response from statistics server. Statistics not sent"
-
Error
- "Internal error. Cannot process request #12345 Error:...."
- "Cannot perform login: credentials DB not responding"
-
Critical
- "Critical panic received: .... Shutting down"
- "Fatal error: ... App is shutting down to prevent data corruption or loss"
Example
func internalCalculationFunc(x, y int) (result int, err error) {beego.Debug("calculating z. x:",x," y:",y)z := yswitch {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 = xdefault :beego.Trace("default")z += x}retVal := z-3beego.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," y:", 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默認(rèn)會(huì)解析當(dāng)前應(yīng)用下的conf/app.conf文件
通過這個(gè)文件你可以初始化很多beego的默認(rèn)參數(shù)
appname = beepkg httpaddr = "127.0.0.1" httpport = 9090 runmode ="dev" autorender = false autorecover = false viewspath = "myview"上面這些參數(shù)會(huì)替換beego默認(rèn)的一些參數(shù)。
你可以在配置文件中配置應(yīng)用需要用的一些配置信息,例如下面所示的數(shù)據(jù)庫信息:
mysqluser = "root" mysqlpass = "rootpass" mysqlurls = "127.0.0.1" mysqldb = "beego"那么你就可以通過如下的方式獲取設(shè)置的配置信息:
beego.AppConfig.String("mysqluser") beego.AppConfig.String("mysqlpass") beego.AppConfig.String("mysqlurls") beego.AppConfig.String("mysqldb")AppConfig支持如下方法
- Bool(key string) (bool, error)
- Int(key string) (int, error)
- Int64(key string) (int64, error)
- Float(key string) (float64, error)
- String(key string) string
系統(tǒng)默認(rèn)參數(shù)
beego中帶有很多可配置的參數(shù),我們來一一認(rèn)識(shí)一下它們,這樣有利于我們?cè)诮酉聛淼腷eego開發(fā)中可以充分的發(fā)揮他們的作用:
-
BeeApp
beego默認(rèn)啟動(dòng)的一個(gè)應(yīng)用器入口,在應(yīng)用import beego的時(shí)候,在init中已經(jīng)初始化的。
-
AppConfig
beego的配置文件解析之后的對(duì)象,也是在init的時(shí)候初始化的,里面保存有解析conf/app.conf下面所有的參數(shù)數(shù)據(jù)
-
HttpAddr
應(yīng)用監(jiān)聽地址,默認(rèn)為空,監(jiān)聽所有的網(wǎng)卡IP
-
HttpPort
應(yīng)用監(jiān)聽端口,默認(rèn)為8080
-
AppName
應(yīng)用名稱,默認(rèn)是beego
-
RunMode
應(yīng)用的模式,默認(rèn)是dev,為開發(fā)模式,在開發(fā)模式下出錯(cuò)會(huì)提示友好的出錯(cuò)頁面,如前面錯(cuò)誤描述中所述。
-
AutoRender
是否模板自動(dòng)渲染,默認(rèn)值為true,對(duì)于API類型的應(yīng)用,應(yīng)用需要把該選項(xiàng)設(shè)置為false,不需要渲染模板。
-
RecoverPanic
是否異常恢復(fù),默認(rèn)值為true,即當(dāng)應(yīng)用出現(xiàn)異常的情況,通過recover恢復(fù)回來,而不會(huì)導(dǎo)致應(yīng)用異常退出。
-
PprofOn
是否啟用pprof,默認(rèn)是false,當(dāng)開啟之后,用戶可以通過如下地址查看相應(yīng)的goroutine執(zhí)行情況
/debug/pprof /debug/pprof/cmdline /debug/pprof/profile /debug/pprof/symbol關(guān)于pprof的信息,請(qǐng)參考官方的描述pprof
-
ViewsPath
模板路徑,默認(rèn)值是views
-
SessionOn
session是否開啟,默認(rèn)是false
-
SessionProvider
session的引擎,默認(rèn)是memory
-
SessionName
存在客戶端的cookie名稱,默認(rèn)值是beegosessionID
-
SessionGCMaxLifetime
session過期時(shí)間,默認(rèn)值是3600秒
-
SessionSavePath
session保存路徑,默認(rèn)是空
-
UseFcgi
是否啟用fastcgi,默認(rèn)是false
-
MaxMemory
文件上傳默認(rèn)內(nèi)存緩存大小,默認(rèn)值是1 << 26(64M)
第三方應(yīng)用集成
beego支持第三方應(yīng)用的集成,用戶可以自定義http.Handler,用戶可以通過如下方式進(jìn)行注冊(cè)路由:
beego.RouterHandler("/chat/:info(.*)", sockjshandler)sockjshandler實(shí)現(xiàn)了接口http.Handler。
目前在beego的example中有支持sockjs的chat例子,示例代碼如下:
package mainimport ("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().RemoteAddraddr := 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() }通過上面的代碼很簡單的實(shí)現(xiàn)了一個(gè)多人的聊天室。上面這個(gè)只是一個(gè)sockjs的例子,我想通過大家自定義http.Handler,可以有很多種方式來進(jìn)行擴(kuò)展beego應(yīng)用。
部署編譯應(yīng)用
Go語言的應(yīng)用最后編譯之后是一個(gè)二進(jìn)制文件,你只需要copy這個(gè)應(yīng)用到服務(wù)器上,運(yùn)行起來就行。beego由于帶有幾個(gè)靜態(tài)文件、配置文件、模板文件三個(gè)目錄,所以用戶部署的時(shí)候需要同時(shí)copy這三個(gè)目錄到相應(yīng)的部署應(yīng)用之下,下面以我實(shí)際的應(yīng)用部署為例:
$ 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目錄下面就會(huì)顯示如下的目錄結(jié)構(gòu):
. ├── conf │ ├── app.conf ├── static │ ├── css │ ├── img │ └── js └── views└── index.tpl ├── beepkg這樣我們就已經(jīng)把我們需要的應(yīng)用搬到服務(wù)器了,那么接下來就可以開始部署了,我現(xiàn)在服務(wù)器端用兩種方式來run,
-
Supervisord
安裝和配置見Supervisord
-
nohup方式
nohup ./beepkg &
個(gè)人比較推薦第一種方式,可以很好的管理起來應(yīng)用
總結(jié)
- 上一篇: html如何大小写转换键,怎么把26键变
- 下一篇: SSL证书申购指南教程