installation, incomplete quick start
Showing
3 changed files
with
999 additions
and
1 deletions
docs/en/Install.md
0 → 100644
| 1 | #Installation | ||
| 2 | Beego is a simple web framework, but it uses many third-party packages, so you have to install all dependency packages also. | ||
| 3 | |||
| 4 | - Before anything you do, you have to check that you installed Go in your computer, see more detail about Go installation in my book: [Chapter 1](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/01.1.md) | ||
| 5 | - Use `go get ` to install Beego: | ||
| 6 | |||
| 7 | go get github.com/astaxie/beego | ||
| 8 | |||
| 9 | - Install bee tools for fast-develop Beego applications: | ||
| 10 | |||
| 11 | go get github.com/astaxie/bee | ||
| 12 | |||
| 13 | Good job, you're ready to Beego with powerful bee tools! | ||
| 14 | |||
| 15 |  | ||
| 16 | |||
| 17 | Beego has following dependency packages: | ||
| 18 | |||
| 19 | - Session module: [github.com/astaxie/beego/session](github.com/astaxie/beego/session) | ||
| 20 | - To support redis engine: [github.com/garyburd/redigo/redis](github.com/garyburd/redigo/redis) | ||
| 21 | - To support mysql engine: [github.com/go-sql-driver/mysql](github.com/go-sql-driver/mysql) | ||
| 22 | - To support markdown as template function: [github.com/russross/blackfriday](github.com/russross/blackfriday) | ||
| 23 | |||
| 24 | - [Introduction](README.md) | ||
| 25 | - [Quick start](Quickstart.md) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
docs/en/Quickstart.md
0 → 100644
| 1 | # Quick start | ||
| 2 | Hey, you say you've never heard about Beego and don't know how to use it? Don't worry, after you read this section, you will know a lot about Beego. Before you start reading, make sure you installed Beego in your computer, if not, check this tutorial: [Installation](Install.md) | ||
| 3 | |||
| 4 | **Navigation** | ||
| 5 | |||
| 6 | - [Hello world](#-1) | ||
| 7 | - [New project](#-2) | ||
| 8 | - [Development mode](#-3) | ||
| 9 | - [Router](#-4) | ||
| 10 | - [Static files](#-5) | ||
| 11 | - [Filter and middleware](#-6) | ||
| 12 | - [Controller](#-7) | ||
| 13 | - [Template](#-8) | ||
| 14 | - [Handle request](#request) | ||
| 15 | - [Redirect and error](#-15) | ||
| 16 | - [Handle response](#response) | ||
| 17 | - [Sessions](#sessions) | ||
| 18 | - [Cache](#cache) | ||
| 19 | - [Safe map](#map) | ||
| 20 | - [Log](#-16) | ||
| 21 | - [Configuration](#-17) | ||
| 22 | - [Beego arguments](#-18) | ||
| 23 | - [Integrated third-party applications](#-19) | ||
| 24 | - [Deployment](#-20) | ||
| 25 | |||
| 26 | ## Hello world | ||
| 27 | This is an example of "Hello world" in Beego: | ||
| 28 | |||
| 29 | package main | ||
| 30 | |||
| 31 | import ( | ||
| 32 | "github.com/astaxie/beego" | ||
| 33 | ) | ||
| 34 | |||
| 35 | type MainController struct { | ||
| 36 | beego.Controller | ||
| 37 | } | ||
| 38 | |||
| 39 | func (this *MainController) Get() { | ||
| 40 | this.Ctx.WriteString("hello world") | ||
| 41 | } | ||
| 42 | |||
| 43 | func main() { | ||
| 44 | beego.Router("/", &MainController{}) | ||
| 45 | beego.Run() | ||
| 46 | } | ||
| 47 | |||
| 48 | Save file as "hello.go", build and run it: | ||
| 49 | |||
| 50 | $ go build main.go | ||
| 51 | $ ./hello | ||
| 52 | |||
| 53 | Open address [http://127.0.0.1:8080](http://127.0.0.1:8080) in your browser and you will see "hello world". | ||
| 54 | |||
| 55 | What happened in behind above example? | ||
| 56 | |||
| 57 | 1. We import package `github.com/astaxie/beego`. As we know that Go initialize packages and runs init() function in every package(more detail [here](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/02.3.md#main-function-and-init-function)), so Beego initializes the BeeApp application at this time. | ||
| 58 | 2. Define controller. We define a struct called `MainController` with a anonymous field `beego.Controller`, so the `MainController` has all methods that `beego.Controller` has. | ||
| 59 | 3. Define RESTful methods. Once we use anonymous combination, `MainController` has already had `Get`, `Post`, `Delete`, `Put` and other methods, these methods will be called when user sends corresponding request, like `Post` method for requests that are using POST method. Therefore, after we overloaded `Get` method in `MainController`, all GET requests will use `Get` method in `MainController` instead of in `beego.Controller`. | ||
| 60 | 4. Define main function. All applications in Go use main function as entry point as C does. | ||
| 61 | 5. Register routers, it tells Beego which controller is responsibility for specific requests. Here we register `/` for `MainController`, so all requests in `/` will be handed to `MainController`. Be aware that the first argument is the path and the second one is pointer of controller that you want to register. | ||
| 62 | 6. Run application in port 8080 as default, press `Ctrl+c` to exit. | ||
| 63 | |||
| 64 | ## New project | ||
| 65 | Get into your $GOPATH, then use following command to setup Beego project: | ||
| 66 | |||
| 67 | bee create hello | ||
| 68 | |||
| 69 | It generates folders and files for your project, directory structure as follows: | ||
| 70 | |||
| 71 | . | ||
| 72 | ├── conf | ||
| 73 | │ └── app.conf | ||
| 74 | ├── controllers | ||
| 75 | │ └── default.go | ||
| 76 | ├── main.go | ||
| 77 | ├── models | ||
| 78 | ├── static | ||
| 79 | │ ├── css | ||
| 80 | │ ├── img | ||
| 81 | │ └── js | ||
| 82 | └── views | ||
| 83 | └── index.tpl | ||
| 84 | |||
| 85 | ## Development mode | ||
| 86 | Beego uses development mode as default, you can use following code to change mode in your application: | ||
| 87 | |||
| 88 | beego.RunMode = "pro" | ||
| 89 | |||
| 90 | Or use configuration file in `conf/app.conf`, and input following content: | ||
| 91 | |||
| 92 | runmode = pro | ||
| 93 | |||
| 94 | No differences between two ways. | ||
| 95 | |||
| 96 | In development mode, you have following effects: | ||
| 97 | |||
| 98 | - If you don't have directory `views`, it prints following error prompt: | ||
| 99 | |||
| 100 | 2013/04/13 19:36:17 [W] [stat views: no such file or directory] | ||
| 101 | |||
| 102 | - It doesn't cache template and reload every time. | ||
| 103 | - If panic occurs in your server, it prints information like following screen shot: | ||
| 104 | |||
| 105 |  | ||
| 106 | |||
| 107 | ## Router | ||
| 108 | |||
| 109 | 路由的主要功能是实现从请求地址到实现方法,beego中封装了`Controller`,所以路由是从路径到`ControllerInterface`的过程,`ControllerInterface`的方法有如下: | ||
| 110 | |||
| 111 | type ControllerInterface interface { | ||
| 112 | Init(ct *Context, cn string) | ||
| 113 | Prepare() | ||
| 114 | Get() | ||
| 115 | Post() | ||
| 116 | Delete() | ||
| 117 | Put() | ||
| 118 | Head() | ||
| 119 | Patch() | ||
| 120 | Options() | ||
| 121 | Finish() | ||
| 122 | Render() error | ||
| 123 | } | ||
| 124 | |||
| 125 | 这些方法`beego.Controller`都已经实现了,所以只要用户定义struct的时候匿名包含就可以了。当然更灵活的方法就是用户可以去自定义类似的方法,然后实现自己的逻辑。 | ||
| 126 | |||
| 127 | 用户可以通过如下的方式进行路由设置: | ||
| 128 | |||
| 129 | beego.Router("/", &controllers.MainController{}) | ||
| 130 | beego.Router("/admin", &admin.UserController{}) | ||
| 131 | beego.Router("/admin/index", &admin.ArticleController{}) | ||
| 132 | beego.Router("/admin/addpkg", &admin.AddController{}) | ||
| 133 | |||
| 134 | 为了用户更加方便的路由设置,beego参考了sinatra的路由实现,支持多种方式的路由: | ||
| 135 | |||
| 136 | - beego.Router("/api/:id([0-9]+)", &controllers.RController{}) | ||
| 137 | 自定义正则匹配 //匹配 /api/123 :id= 123 | ||
| 138 | |||
| 139 | - beego.Router("/news/:all", &controllers.RController{}) | ||
| 140 | 全匹配方式 //匹配 /news/path/to/123.html :all= path/to/123.html | ||
| 141 | |||
| 142 | - beego.Router("/user/:username([\w]+)", &controllers.RController{}) | ||
| 143 | 正则字符串匹配 //匹配 /user/astaxie :username = astaxie | ||
| 144 | |||
| 145 | - beego.Router("/download/*.*", &controllers.RController{}) | ||
| 146 | *匹配方式 //匹配 /download/file/api.xml :path= file/api :ext=xml | ||
| 147 | |||
| 148 | - beego.Router("/download/ceshi/*", &controllers.RController{}) | ||
| 149 | *全匹配方式 //匹配 /download/ceshi/file/api.json :splat=file/api.json | ||
| 150 | |||
| 151 | - beego.Router("/:id:int", &controllers.RController{}) | ||
| 152 | int类型设置方式 //匹配 :id为int类型,框架帮你实现了正则([0-9]+) | ||
| 153 | |||
| 154 | - beego.Router("/:hi:string", &controllers.RController{}) | ||
| 155 | string类型设置方式 //匹配 :hi为string类型。框架帮你实现了正则([\w]+) | ||
| 156 | |||
| 157 | ## 静态文件 | ||
| 158 | Go语言内部其实已经提供了`http.ServeFile`,通过这个函数可以实现静态文件的服务。beego针对这个功能进行了一层封装,通过下面的方式进行静态文件注册: | ||
| 159 | |||
| 160 | beego.SetStaticPath("/static","public") | ||
| 161 | |||
| 162 | - 第一个参数是路径,url路径信息 | ||
| 163 | - 第二个参数是静态文件目录(相对应用所在的目录) | ||
| 164 | |||
| 165 | beego支持多个目录的静态文件注册,用户可以注册如下的静态文件目录: | ||
| 166 | |||
| 167 | beego.SetStaticPath("/images","images") | ||
| 168 | beego.SetStaticPath("/css","css") | ||
| 169 | beego.SetStaticPath("/js","js") | ||
| 170 | |||
| 171 | 设置了如上的静态目录之后,用户访问`/images/login/login.png`,那么就会访问应用对应的目录下面的`images/login/login.png`文件。如果是访问`/static/img/logo.png`,那么就访问`public/img/logo.png`文件。 | ||
| 172 | |||
| 173 | ## 过滤和中间件 | ||
| 174 | beego支持自定义过滤中间件,例如安全验证,强制跳转等 | ||
| 175 | |||
| 176 | 如下例子所示,验证用户名是否是admin,应用于全部的请求: | ||
| 177 | |||
| 178 | var FilterUser = func(w http.ResponseWriter, r *http.Request) { | ||
| 179 | if r.URL.User == nil || r.URL.User.Username() != "admin" { | ||
| 180 | http.Error(w, "", http.StatusUnauthorized) | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | beego.Filter(FilterUser) | ||
| 185 | |||
| 186 | 还可以通过参数进行过滤,如果匹配参数就执行 | ||
| 187 | |||
| 188 | beego.Router("/:id([0-9]+)", &admin.EditController{}) | ||
| 189 | beego.FilterParam("id", func(rw http.ResponseWriter, r *http.Request) { | ||
| 190 | dosomething() | ||
| 191 | }) | ||
| 192 | |||
| 193 | 当然你还可以通过前缀过滤 | ||
| 194 | |||
| 195 | beego.FilterPrefixPath("/admin", func(rw http.ResponseWriter, r *http.Request) { | ||
| 196 | dosomething() | ||
| 197 | }) | ||
| 198 | |||
| 199 | ## 控制器设计 | ||
| 200 | 基于beego的Controller设计,只需要匿名组合`beego.Controller`就可以了,如下所示: | ||
| 201 | |||
| 202 | type xxxController struct { | ||
| 203 | beego.Controller | ||
| 204 | } | ||
| 205 | |||
| 206 | `beego.Controller`实现了接口`beego.ControllerInterface`,`beego.ControllerInterface`定义了如下函数: | ||
| 207 | |||
| 208 | - Init(ct *Context, cn string) | ||
| 209 | |||
| 210 | 这个函数主要初始化了Context、相应的Controller名称,模板名,初始化模板参数的容器Data | ||
| 211 | |||
| 212 | - Prepare() | ||
| 213 | |||
| 214 | 这个函数主要是为了用户扩展用的,这个函数会在下面定义的这些Method方法之前执行,用户可以重写这个函数实现类似用户验证之类。 | ||
| 215 | |||
| 216 | - Get() | ||
| 217 | |||
| 218 | 如果用户请求的HTTP Method是GET, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Get请求. | ||
| 219 | |||
| 220 | - Post() | ||
| 221 | |||
| 222 | 如果用户请求的HTTP Method是POST, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Post请求. | ||
| 223 | |||
| 224 | - Delete() | ||
| 225 | |||
| 226 | 如果用户请求的HTTP Method是DELETE, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Delete请求. | ||
| 227 | |||
| 228 | - Put() | ||
| 229 | |||
| 230 | 如果用户请求的HTTP Method是PUT, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Put请求. | ||
| 231 | |||
| 232 | - Head() | ||
| 233 | |||
| 234 | 如果用户请求的HTTP Method是HEAD, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Head请求. | ||
| 235 | |||
| 236 | - Patch() | ||
| 237 | |||
| 238 | 如果用户请求的HTTP Method是PATCH, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Patch请求. | ||
| 239 | |||
| 240 | - Options() | ||
| 241 | |||
| 242 | 如果用户请求的HTTP Method是OPTIONS, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Options请求. | ||
| 243 | |||
| 244 | - Finish() | ||
| 245 | |||
| 246 | 这个函数实在执行完相应的http Method方法之后执行的,默认是空,用户可以在子Strcut中重写这个函数,执行例如数据库关闭,清理数据之类的工作 | ||
| 247 | |||
| 248 | - Render() error | ||
| 249 | |||
| 250 | 这个函数主要用来实现渲染模板,如果beego.AutoRender为true的情况下才会执行。 | ||
| 251 | |||
| 252 | 所以通过子struct的方法重写,用户就可以实现自己的逻辑,接下来我们看一个实际的例子: | ||
| 253 | |||
| 254 | type AddController struct { | ||
| 255 | beego.Controller | ||
| 256 | } | ||
| 257 | |||
| 258 | func (this *AddController) Prepare() { | ||
| 259 | |||
| 260 | } | ||
| 261 | |||
| 262 | func (this *AddController) Get() { | ||
| 263 | this.Data["content"] ="value" | ||
| 264 | this.Layout = "admin/layout.html" | ||
| 265 | this.TplNames = "admin/add.tpl" | ||
| 266 | } | ||
| 267 | |||
| 268 | func (this *AddController) Post() { | ||
| 269 | pkgname := this.GetString("pkgname") | ||
| 270 | content := this.GetString("content") | ||
| 271 | pk := models.GetCruPkg(pkgname) | ||
| 272 | if pk.Id == 0 { | ||
| 273 | var pp models.PkgEntity | ||
| 274 | pp.Pid = 0 | ||
| 275 | pp.Pathname = pkgname | ||
| 276 | pp.Intro = pkgname | ||
| 277 | models.InsertPkg(pp) | ||
| 278 | pk = models.GetCruPkg(pkgname) | ||
| 279 | } | ||
| 280 | var at models.Article | ||
| 281 | at.Pkgid = pk.Id | ||
| 282 | at.Content = content | ||
| 283 | models.InsertArticle(at) | ||
| 284 | this.Ctx.Redirect(302, "/admin/index") | ||
| 285 | } | ||
| 286 | |||
| 287 | ## 模板处理 | ||
| 288 | ### 模板目录 | ||
| 289 | beego中默认的模板目录是`views`,用户可以把你的模板文件放到该目录下,beego会自动在该目录下的所有模板文件进行解析并缓存,开发模式下会每次重新解析,不做缓存。当然用户可以通过如下的方式改变模板的目录: | ||
| 290 | |||
| 291 | beego.ViewsPath = "/myviewpath" | ||
| 292 | ### 自动渲染 | ||
| 293 | beego中用户无需手动的调用渲染输出模板,beego会自动的在调用玩相应的method方法之后调用Render函数,当然如果你的应用是不需要模板输出的,那么你可以在配置文件或者在main.go中设置关闭自动渲染。 | ||
| 294 | |||
| 295 | 配置文件配置如下: | ||
| 296 | |||
| 297 | autorender = false | ||
| 298 | |||
| 299 | main.go文件中设置如下: | ||
| 300 | |||
| 301 | beego.AutoRender = false | ||
| 302 | |||
| 303 | ### 模板数据 | ||
| 304 | 模板中的数据是通过在Controller中`this.Data`获取的,所以如果你想在模板中获取内容`{{.Content}}`,那么你需要在Controller中如下设置: | ||
| 305 | |||
| 306 | this.Data["Context"] = "value" | ||
| 307 | |||
| 308 | ### 模板名称 | ||
| 309 | beego采用了Go语言内置的模板引擎,所有模板的语法和Go的一模一样,至于如何写模板文件,详细的请参考[模板教程](https://github.com/astaxie/build-web-application-with-golang/blob/master/ebook/07.4.md)。 | ||
| 310 | |||
| 311 | 用户通过在Controller的对应方法中设置相应的模板名称,beego会自动的在viewpath目录下查询该文件并渲染,例如下面的设置,beego会在admin下面找add.tpl文件进行渲染: | ||
| 312 | |||
| 313 | this.TplNames = "admin/add.tpl" | ||
| 314 | |||
| 315 | 我们看到上面的模板后缀名是tpl,beego默认情况下支持tpl和html后缀名的模板文件,如果你的后缀名不是这两种,请进行如下设置: | ||
| 316 | |||
| 317 | beego.AddTemplateExt("你文件的后缀名") | ||
| 318 | |||
| 319 | 当你设置了自动渲染,然后在你的Controller中没有设置任何的TplNames,那么beego会自动设置你的模板文件如下: | ||
| 320 | |||
| 321 | c.TplNames = c.ChildName + "/" + c.Ctx.Request.Method + "." + c.TplExt | ||
| 322 | |||
| 323 | 也就是你对应的Controller名字+请求方法名.模板后缀,也就是如果你的Controller名是`AddController`,请求方法是`POST`,默认的文件后缀是`tpl`,那么就会默认请求`/viewpath/AddController/POST.tpl`文件。 | ||
| 324 | |||
| 325 | ### lauout设计 | ||
| 326 | beego支持layout设计,例如你在管理系统中,其实整个的管理界面是固定的,支会变化中间的部分,那么你可以通过如下的设置: | ||
| 327 | |||
| 328 | this.Layout = "admin/layout.html" | ||
| 329 | this.TplNames = "admin/add.tpl" | ||
| 330 | |||
| 331 | 在layout.html中你必须设置如下的变量: | ||
| 332 | |||
| 333 | {{.LayoutContent}} | ||
| 334 | |||
| 335 | beego就会首先解析TplNames指定的文件,获取内容赋值给LayoutContent,然后最后渲染layout.html文件。 | ||
| 336 | |||
| 337 | 目前采用首先把目录下所有的文件进行缓存,所以用户还可以通过类似这样的方式实现layout: | ||
| 338 | |||
| 339 | {{template "header.html"}} | ||
| 340 | 处理逻辑 | ||
| 341 | {{template "footer.html"}} | ||
| 342 | |||
| 343 | ### 模板函数 | ||
| 344 | beego支持用户定义模板函数,但是必须在`beego.Run()`调用之前,设置如下: | ||
| 345 | |||
| 346 | func hello(in string)(out string){ | ||
| 347 | out = in + "world" | ||
| 348 | return | ||
| 349 | } | ||
| 350 | |||
| 351 | beego.AddFuncMap("hi",hello) | ||
| 352 | |||
| 353 | 定义之后你就可以在模板中这样使用了: | ||
| 354 | |||
| 355 | {{.Content | hi}} | ||
| 356 | |||
| 357 | 目前beego内置的模板函数有如下: | ||
| 358 | |||
| 359 | * markdown | ||
| 360 | |||
| 361 | 实现了把markdown文本转化为html信息,使用方法{{markdown .Content}} | ||
| 362 | * dateformat | ||
| 363 | |||
| 364 | 实现了时间的格式化,返回字符串,使用方法{{dateformat .Time "2006-01-02T15:04:05Z07:00"}} | ||
| 365 | * date | ||
| 366 | |||
| 367 | 实现了类似PHP的date函数,可以很方便的根据字符串返回时间,使用方法{{date .T "Y-m-d H:i:s"}} | ||
| 368 | * compare | ||
| 369 | |||
| 370 | 实现了比较两个对象的比较,如果相同返回true,否者false,使用方法{{compare .A .B}} | ||
| 371 | * substr | ||
| 372 | |||
| 373 | 实现了字符串的截取,支持中文截取的完美截取,使用方法{{substr .Str 0 30}} | ||
| 374 | * html2str | ||
| 375 | |||
| 376 | 实现了把html转化为字符串,剔除一些script、css之类的元素,返回纯文本信息,使用方法{{html2str .Htmlinfo}} | ||
| 377 | * str2html | ||
| 378 | |||
| 379 | 实现了把相应的字符串当作HTML来输出,不转义,使用方法{{str2html .Strhtml}} | ||
| 380 | * htmlquote | ||
| 381 | |||
| 382 | 实现了基本的html字符转义,使用方法{{htmlquote .quote}} | ||
| 383 | * htmlunquote | ||
| 384 | |||
| 385 | 实现了基本的反转移字符,使用方法{{htmlunquote .unquote}} | ||
| 386 | |||
| 387 | ## request处理 | ||
| 388 | 我们经常需要获取用户传递的数据,包括Get、POST等方式的请求,beego里面会自动解析这些数据,你可以通过如下方式获取数据 | ||
| 389 | |||
| 390 | - GetString(key string) string | ||
| 391 | - GetInt(key string) (int64, error) | ||
| 392 | - GetBool(key string) (bool, error) | ||
| 393 | |||
| 394 | 使用例子如下: | ||
| 395 | |||
| 396 | func (this *MainController) Post() { | ||
| 397 | jsoninfo := this.GetString("jsoninfo") | ||
| 398 | if jsoninfo == "" { | ||
| 399 | this.Ctx.WriteString("jsoninfo is empty") | ||
| 400 | return | ||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 404 | 如果你需要的数据可能是其他类型的,例如是int类型而不是int64,那么你需要这样处理: | ||
| 405 | |||
| 406 | func (this *MainController) Post() { | ||
| 407 | id := this.Input().Get("id") | ||
| 408 | intid, err := strconv.Atoi(id) | ||
| 409 | } | ||
| 410 | |||
| 411 | 更多其他的request的信息,用户可以通过`this.Ctx.Request`获取信息,关于该对象的属性和方法参考手册[Request](http://golang.org/pkg/net/http/#Request) | ||
| 412 | |||
| 413 | ### 文件上传 | ||
| 414 | 在beego中你可以很容易的处理文件上传,就是别忘记在你的form表单中增加这个属性`enctype="multipart/form-data"`,否者你的浏览器不会传输你的上传文件。 | ||
| 415 | |||
| 416 | 文件上传之后一般是放在系统的内存里面,如果文件的size大于设置的缓存内存大小,那么就放在临时文件中,默认的缓存内存是64M,你可以通过如下来调整这个缓存内存大小: | ||
| 417 | |||
| 418 | beego.MaxMemory = 1<<22 | ||
| 419 | |||
| 420 | 或者在配置文件中通过如下设置 | ||
| 421 | |||
| 422 | maxmemory = 1<<22 | ||
| 423 | |||
| 424 | beego提供了两个很方便的方法来处理文件上传: | ||
| 425 | |||
| 426 | - GetFile(key string) (multipart.File, *multipart.FileHeader, error) | ||
| 427 | |||
| 428 | 该方法主要用于用户读取表单中的文件名`the_file`,然后返回相应的信息,用户根据这些变量来处理文件上传:过滤、保存文件等。 | ||
| 429 | |||
| 430 | - SaveToFile(fromfile, tofile string) error | ||
| 431 | |||
| 432 | 该方法是在GetFile的基础上实现了快速保存的功能 | ||
| 433 | |||
| 434 | 保存的代码例子如下: | ||
| 435 | |||
| 436 | func (this *MainController) Post() { | ||
| 437 | this.SaveToFile("the_file","/var/www/uploads/uploaded_file.txt"") | ||
| 438 | } | ||
| 439 | |||
| 440 | ### JSON和XML输出 | ||
| 441 | beego当初设计的时候就考虑了API功能的设计,而我们在设计API的时候经常是输出JSON或者XML数据,那么beego提供了这样的方式直接输出: | ||
| 442 | |||
| 443 | JSON数据直接输出,设置`content-type`为`application/json`: | ||
| 444 | |||
| 445 | func (this *AddController) Get() { | ||
| 446 | mystruct := { ... } | ||
| 447 | this.Data["json"] = &mystruct | ||
| 448 | this.ServeJson() | ||
| 449 | } | ||
| 450 | |||
| 451 | XML数据直接输出,设置`content-type`为`application/xml`: | ||
| 452 | |||
| 453 | func (this *AddController) Get() { | ||
| 454 | mystruct := { ... } | ||
| 455 | this.Data["xml"]=&mystruct | ||
| 456 | this.ServeXml() | ||
| 457 | } | ||
| 458 | |||
| 459 | ## 跳转和错误 | ||
| 460 | 我们在做Web开发的时候,经常会遇到页面调整和错误处理,beego这这方面也进行了考虑,通过`Redirect`方法来进行跳转: | ||
| 461 | |||
| 462 | func (this *AddController) Get() { | ||
| 463 | this.Redirect("/", 302) | ||
| 464 | } | ||
| 465 | |||
| 466 | @todo 错误处理还需要后期改进 | ||
| 467 | |||
| 468 | ## response处理 | ||
| 469 | response可能会有集中情况: | ||
| 470 | |||
| 471 | 1. 模板输出 | ||
| 472 | |||
| 473 | 模板输出上面模板介绍里面已经介绍,beego会在执行完相应的Controller里面的对应的Method之后输出到模板。 | ||
| 474 | |||
| 475 | 2. 跳转 | ||
| 476 | |||
| 477 | 上一节介绍的跳转就是我们经常用到的页面之间的跳转 | ||
| 478 | |||
| 479 | 3. 字符串输出 | ||
| 480 | |||
| 481 | 有些时候我们只是想输出相应的一个字符串,那么我们可以通过如下的代码实现 | ||
| 482 | |||
| 483 | this.Ctx.WriteString("ok") | ||
| 484 | |||
| 485 | ## Sessions | ||
| 486 | beego内置了session模块,目前session模块支持的后端引擎包括memory、file、mysql、redis四中,用户也可以根据相应的interface实现自己的引擎。 | ||
| 487 | |||
| 488 | beego中使用session相当方便,只要在main入口函数中设置如下: | ||
| 489 | |||
| 490 | beego.SessionOn = true | ||
| 491 | |||
| 492 | 或者通过配置文件配置如下: | ||
| 493 | |||
| 494 | sessionon = true | ||
| 495 | |||
| 496 | 通过这种方式就可以开启session,如何使用session,请看下面的例子: | ||
| 497 | |||
| 498 | func (this *MainController) Get() { | ||
| 499 | v := this.GetSession("asta") | ||
| 500 | if v == nil { | ||
| 501 | this.SetSession("asta", int(1)) | ||
| 502 | this.Data["num"] = 0 | ||
| 503 | } else { | ||
| 504 | this.SetSession("asta", v.(int)+1) | ||
| 505 | this.Data["num"] = v.(int) | ||
| 506 | } | ||
| 507 | this.TplNames = "index.tpl" | ||
| 508 | } | ||
| 509 | |||
| 510 | 上面的例子中我们知道session有几个方便的方法: | ||
| 511 | |||
| 512 | - SetSession(name string, value interface{}) | ||
| 513 | - GetSession(name string) interface{} | ||
| 514 | - DelSession(name string) | ||
| 515 | |||
| 516 | session操作主要有设置session、获取session、删除session | ||
| 517 | |||
| 518 | 当然你要可以通过下面的方式自己控制相应的逻辑这些逻辑: | ||
| 519 | |||
| 520 | sess:=this.StartSession() | ||
| 521 | defer sess.SessionRelease() | ||
| 522 | |||
| 523 | sess对象具有如下方法: | ||
| 524 | |||
| 525 | * sess.Set() | ||
| 526 | * sess.Get() | ||
| 527 | * sess.Delete() | ||
| 528 | * sess.SessionID() | ||
| 529 | |||
| 530 | 但是我还是建议大家采用SetSession、GetSession、DelSession三个方法来操作,避免自己在操作的过程中资源没释放的问题。 | ||
| 531 | |||
| 532 | 关于Session模块使用中的一些参数设置: | ||
| 533 | |||
| 534 | - SessionOn | ||
| 535 | |||
| 536 | 设置是否开启Session,默认是false,配置文件对应的参数名:sessionon | ||
| 537 | |||
| 538 | - SessionProvider | ||
| 539 | |||
| 540 | 设置Session的引擎,默认是memory,目前支持还有file、mysql、redis等,配置文件对应的参数名:sessionprovider | ||
| 541 | |||
| 542 | - SessionName | ||
| 543 | |||
| 544 | 设置cookies的名字,Session默认是保存在用户的浏览器cookies里面的,默认名是beegosessionID,配置文件对应的参数名是:sessionname | ||
| 545 | |||
| 546 | - SessionGCMaxLifetime | ||
| 547 | |||
| 548 | 设置Session过期的时间,默认值是3600秒,配置文件对应的参数:sessiongcmaxlifetime | ||
| 549 | |||
| 550 | - SessionSavePath | ||
| 551 | |||
| 552 | 设置对应file、mysql、redis引擎的保存路径或者链接地址,默认值是空,配置文件对应的参数:sessionsavepath | ||
| 553 | |||
| 554 | |||
| 555 | 当SessionProvider为file时,SessionSavePath是只保存文件的目录,如下所示: | ||
| 556 | |||
| 557 | beego.SessionProvider = "file" | ||
| 558 | beego.SessionSavePath = "./tmp" | ||
| 559 | |||
| 560 | 当SessionProvider为mysql时,SessionSavePath是链接地址,采用[go-sql-driver](https://github.com/go-sql-driver/mysql),如下所示: | ||
| 561 | |||
| 562 | beego.SessionProvider = "mysql" | ||
| 563 | beego.SessionSavePath = "username:password@protocol(address)/dbname?param=value" | ||
| 564 | |||
| 565 | 当SessionProvider为redis时,SessionSavePath是redis的链接地址,采用了[redigo](https://github.com/garyburd/redigo),如下所示: | ||
| 566 | |||
| 567 | beego.SessionProvider = "redis" | ||
| 568 | beego.SessionSavePath = "127.0.0.1:6379" | ||
| 569 | |||
| 570 | ## Cache设置 | ||
| 571 | beego内置了一个cache模块,实现了类似memcache的功能,缓存数据在内存中,主要的使用方法如下: | ||
| 572 | |||
| 573 | var ( | ||
| 574 | urllist *beego.BeeCache | ||
| 575 | ) | ||
| 576 | |||
| 577 | func init() { | ||
| 578 | urllist = beego.NewBeeCache() | ||
| 579 | urllist.Every = 0 //不过期 | ||
| 580 | urllist.Start() | ||
| 581 | } | ||
| 582 | |||
| 583 | func (this *ShortController) Post() { | ||
| 584 | var result ShortResult | ||
| 585 | longurl := this.Input().Get("longurl") | ||
| 586 | beego.Info(longurl) | ||
| 587 | result.UrlLong = longurl | ||
| 588 | urlmd5 := models.GetMD5(longurl) | ||
| 589 | beego.Info(urlmd5) | ||
| 590 | if urllist.IsExist(urlmd5) { | ||
| 591 | result.UrlShort = urllist.Get(urlmd5).(string) | ||
| 592 | } else { | ||
| 593 | result.UrlShort = models.Generate() | ||
| 594 | err := urllist.Put(urlmd5, result.UrlShort, 0) | ||
| 595 | if err != nil { | ||
| 596 | beego.Info(err) | ||
| 597 | } | ||
| 598 | err = urllist.Put(result.UrlShort, longurl, 0) | ||
| 599 | if err != nil { | ||
| 600 | beego.Info(err) | ||
| 601 | } | ||
| 602 | } | ||
| 603 | this.Data["json"] = result | ||
| 604 | this.ServeJson() | ||
| 605 | } | ||
| 606 | |||
| 607 | 上面这个例子演示了如何使用beego的Cache模块,主要是通过`beego.NewBeeCache`初始化一个对象,然后设置过期时间,开启过期检测,在业务逻辑中就可以通过如下的接口进行增删改的操作: | ||
| 608 | |||
| 609 | - Get(name string) interface{} | ||
| 610 | - Put(name string, value interface{}, expired int) error | ||
| 611 | - Delete(name string) (ok bool, err error) | ||
| 612 | - IsExist(name string) bool | ||
| 613 | |||
| 614 | ## 安全的Map | ||
| 615 | 我们知道在Go语言里面map是非线程安全的,详细的[atomic_maps](http://golang.org/doc/faq#atomic_maps)。但是我们在平常的业务中经常需要用到线程安全的map,特别是在goroutine的情况下,所以beego内置了一个简单的线程安全的map: | ||
| 616 | |||
| 617 | bm := NewBeeMap() | ||
| 618 | if !bm.Set("astaxie", 1) { | ||
| 619 | t.Error("set Error") | ||
| 620 | } | ||
| 621 | if !bm.Check("astaxie") { | ||
| 622 | t.Error("check err") | ||
| 623 | } | ||
| 624 | |||
| 625 | if v := bm.Get("astaxie"); v.(int) != 1 { | ||
| 626 | t.Error("get err") | ||
| 627 | } | ||
| 628 | |||
| 629 | bm.Delete("astaxie") | ||
| 630 | if bm.Check("astaxie") { | ||
| 631 | t.Error("delete err") | ||
| 632 | } | ||
| 633 | |||
| 634 | 上面演示了如何使用线程安全的Map,主要的接口有: | ||
| 635 | |||
| 636 | - Get(k interface{}) interface{} | ||
| 637 | - Set(k interface{}, v interface{}) bool | ||
| 638 | - Check(k interface{}) bool | ||
| 639 | - Delete(k interface{}) | ||
| 640 | |||
| 641 | ## 日志处理 | ||
| 642 | beego默认有一个初始化的BeeLogger对象输出内容到stdout中,你可以通过如下的方式设置自己的输出: | ||
| 643 | |||
| 644 | beego.SetLogger(*log.Logger) | ||
| 645 | |||
| 646 | 只要你的输出符合`*log.Logger`就可以,例如输出到文件: | ||
| 647 | |||
| 648 | fd,err := os.OpenFile("/var/log/beeapp/beeapp.log", os.O_RDWR|os.O_APPEND, 0644) | ||
| 649 | if err != nil { | ||
| 650 | beego.Critical("openfile beeapp.log:", err) | ||
| 651 | return | ||
| 652 | } | ||
| 653 | lg := log.New(fd, "", log.Ldate|log.Ltime) | ||
| 654 | beego.SetLogger(lg) | ||
| 655 | ### 不同级别的log日志函数 | ||
| 656 | |||
| 657 | * Trace(v ...interface{}) | ||
| 658 | * Debug(v ...interface{}) | ||
| 659 | * Info(v ...interface{}) | ||
| 660 | * Warn(v ...interface{}) | ||
| 661 | * Error(v ...interface{}) | ||
| 662 | * Critical(v ...interface{}) | ||
| 663 | |||
| 664 | 你可以通过下面的方式设置不同的日志分级: | ||
| 665 | |||
| 666 | beego.SetLevel(beego.LevelError) | ||
| 667 | |||
| 668 | 当你代码中有很多日志输出之后,如果想上线,但是你不想输出Trace、Debug、Info等信息,那么你可以设置如下: | ||
| 669 | |||
| 670 | beego.SetLevel(beego.LevelWarning) | ||
| 671 | |||
| 672 | 这样的话就不会输出小于这个level的日志,日志的排序如下: | ||
| 673 | |||
| 674 | LevelTrace、LevelDebug、LevelInfo、LevelWarning、 LevelError、LevelCritical | ||
| 675 | |||
| 676 | 用户可以根据不同的级别输出不同的错误信息,如下例子所示: | ||
| 677 | |||
| 678 | ### Examples of log messages | ||
| 679 | - Trace | ||
| 680 | |||
| 681 | * "Entered parse function validation block" | ||
| 682 | * "Validation: entered second 'if'" | ||
| 683 | * "Dictionary 'Dict' is empty. Using default value" | ||
| 684 | - Debug | ||
| 685 | |||
| 686 | * "Web page requested: http://somesite.com Params='...'" | ||
| 687 | * "Response generated. Response size: 10000. Sending." | ||
| 688 | * "New file received. Type:PNG Size:20000" | ||
| 689 | - Info | ||
| 690 | * "Web server restarted" | ||
| 691 | * "Hourly statistics: Requested pages: 12345 Errors: 123 ..." | ||
| 692 | * "Service paused. Waiting for 'resume' call" | ||
| 693 | - Warn | ||
| 694 | * "Cache corrupted for file='test.file'. Reading from back-end" | ||
| 695 | * "Database 192.168.0.7/DB not responding. Using backup 192.168.0.8/DB" | ||
| 696 | * "No response from statistics server. Statistics not sent" | ||
| 697 | - Error | ||
| 698 | * "Internal error. Cannot process request #12345 Error:...." | ||
| 699 | * "Cannot perform login: credentials DB not responding" | ||
| 700 | - Critical | ||
| 701 | * "Critical panic received: .... Shutting down" | ||
| 702 | * "Fatal error: ... App is shutting down to prevent data corruption or loss" | ||
| 703 | |||
| 704 | ### Example | ||
| 705 | |||
| 706 | func internalCalculationFunc(x, y int) (result int, err error) { | ||
| 707 | beego.Debug("calculating z. x:",x," y:",y) | ||
| 708 | z := y | ||
| 709 | switch { | ||
| 710 | case x == 3 : | ||
| 711 | beego.Trace("x == 3") | ||
| 712 | panic("Failure.") | ||
| 713 | case y == 1 : | ||
| 714 | beego.Trace("y == 1") | ||
| 715 | return 0, errors.New("Error!") | ||
| 716 | case y == 2 : | ||
| 717 | beego.Trace("y == 2") | ||
| 718 | z = x | ||
| 719 | default : | ||
| 720 | beego.Trace("default") | ||
| 721 | z += x | ||
| 722 | } | ||
| 723 | retVal := z-3 | ||
| 724 | beego.Debug("Returning ", retVal) | ||
| 725 | |||
| 726 | return retVal, nil | ||
| 727 | } | ||
| 728 | |||
| 729 | func processInput(input inputData) { | ||
| 730 | defer func() { | ||
| 731 | if r := recover(); r != nil { | ||
| 732 | beego.Error("Unexpected error occurred: ", r) | ||
| 733 | outputs <- outputData{result : 0, error : true} | ||
| 734 | } | ||
| 735 | }() | ||
| 736 | beego.Info("Received input signal. x:",input.x," y:", input.y) | ||
| 737 | |||
| 738 | res, err := internalCalculationFunc(input.x, input.y) | ||
| 739 | if err != nil { | ||
| 740 | beego.Warn("Error in calculation:", err.Error()) | ||
| 741 | } | ||
| 742 | |||
| 743 | beego.Info("Returning result: ",res," error: ",err) | ||
| 744 | outputs <- outputData{result : res, error : err != nil} | ||
| 745 | } | ||
| 746 | |||
| 747 | func main() { | ||
| 748 | inputs = make(chan inputData) | ||
| 749 | outputs = make(chan outputData) | ||
| 750 | criticalChan = make(chan int) | ||
| 751 | beego.Info("App started.") | ||
| 752 | |||
| 753 | go consumeResults(outputs) | ||
| 754 | beego.Info("Started receiving results.") | ||
| 755 | |||
| 756 | go generateInputs(inputs) | ||
| 757 | beego.Info("Started sending signals.") | ||
| 758 | |||
| 759 | for { | ||
| 760 | select { | ||
| 761 | case input := <- inputs: | ||
| 762 | processInput(input) | ||
| 763 | case <- criticalChan: | ||
| 764 | beego.Critical("Caught value from criticalChan: Go shut down.") | ||
| 765 | panic("Shut down due to critical fault.") | ||
| 766 | } | ||
| 767 | } | ||
| 768 | } | ||
| 769 | |||
| 770 | ## 配置管理 | ||
| 771 | beego支持解析ini文件, beego默认会解析当前应用下的`conf/app.conf`文件 | ||
| 772 | |||
| 773 | 通过这个文件你可以初始化很多beego的默认参数 | ||
| 774 | |||
| 775 | appname = beepkg | ||
| 776 | httpaddr = "127.0.0.1" | ||
| 777 | httpport = 9090 | ||
| 778 | runmode ="dev" | ||
| 779 | autorender = false | ||
| 780 | autorecover = false | ||
| 781 | viewspath = "myview" | ||
| 782 | |||
| 783 | 上面这些参数会替换beego默认的一些参数。 | ||
| 784 | |||
| 785 | 你可以在配置文件中配置应用需要用的一些配置信息,例如下面所示的数据库信息: | ||
| 786 | |||
| 787 | mysqluser = "root" | ||
| 788 | mysqlpass = "rootpass" | ||
| 789 | mysqlurls = "127.0.0.1" | ||
| 790 | mysqldb = "beego" | ||
| 791 | |||
| 792 | 那么你就可以通过如下的方式获取设置的配置信息: | ||
| 793 | |||
| 794 | beego.AppConfig.String("mysqluser") | ||
| 795 | beego.AppConfig.String("mysqlpass") | ||
| 796 | beego.AppConfig.String("mysqlurls") | ||
| 797 | beego.AppConfig.String("mysqldb") | ||
| 798 | |||
| 799 | AppConfig支持如下方法 | ||
| 800 | |||
| 801 | - Bool(key string) (bool, error) | ||
| 802 | - Int(key string) (int, error) | ||
| 803 | - Int64(key string) (int64, error) | ||
| 804 | - Float(key string) (float64, error) | ||
| 805 | - String(key string) string | ||
| 806 | |||
| 807 | ## 系统默认参数 | ||
| 808 | beego中带有很多可配置的参数,我们来一一认识一下它们,这样有利于我们在接下来的beego开发中可以充分的发挥他们的作用: | ||
| 809 | |||
| 810 | * BeeApp | ||
| 811 | |||
| 812 | beego默认启动的一个应用器入口,在应用import beego的时候,在init中已经初始化的。 | ||
| 813 | |||
| 814 | * AppConfig | ||
| 815 | |||
| 816 | beego的配置文件解析之后的对象,也是在init的时候初始化的,里面保存有解析`conf/app.conf`下面所有的参数数据 | ||
| 817 | |||
| 818 | * HttpAddr | ||
| 819 | |||
| 820 | 应用监听地址,默认为空,监听所有的网卡IP | ||
| 821 | |||
| 822 | * HttpPort | ||
| 823 | |||
| 824 | 应用监听端口,默认为8080 | ||
| 825 | |||
| 826 | * AppName | ||
| 827 | |||
| 828 | 应用名称,默认是beego | ||
| 829 | |||
| 830 | * RunMode | ||
| 831 | |||
| 832 | 应用的模式,默认是dev,为开发模式,在开发模式下出错会提示友好的出错页面,如前面错误描述中所述。 | ||
| 833 | |||
| 834 | * AutoRender | ||
| 835 | |||
| 836 | 是否模板自动渲染,默认值为true,对于API类型的应用,应用需要把该选项设置为false,不需要渲染模板。 | ||
| 837 | |||
| 838 | * RecoverPanic | ||
| 839 | |||
| 840 | 是否异常恢复,默认值为true,即当应用出现异常的情况,通过recover恢复回来,而不会导致应用异常退出。 | ||
| 841 | |||
| 842 | * PprofOn | ||
| 843 | |||
| 844 | 是否启用pprof,默认是false,当开启之后,用户可以通过如下地址查看相应的goroutine执行情况 | ||
| 845 | |||
| 846 | /debug/pprof | ||
| 847 | /debug/pprof/cmdline | ||
| 848 | /debug/pprof/profile | ||
| 849 | /debug/pprof/symbol | ||
| 850 | 关于pprof的信息,请参考官方的描述[pprof](http://golang.org/pkg/net/http/pprof/) | ||
| 851 | |||
| 852 | * ViewsPath | ||
| 853 | |||
| 854 | 模板路径,默认值是views | ||
| 855 | |||
| 856 | * SessionOn | ||
| 857 | |||
| 858 | session是否开启,默认是false | ||
| 859 | |||
| 860 | * SessionProvider | ||
| 861 | |||
| 862 | session的引擎,默认是memory | ||
| 863 | |||
| 864 | * SessionName | ||
| 865 | |||
| 866 | 存在客户端的cookie名称,默认值是beegosessionID | ||
| 867 | |||
| 868 | * SessionGCMaxLifetime | ||
| 869 | |||
| 870 | session过期时间,默认值是3600秒 | ||
| 871 | |||
| 872 | * SessionSavePath | ||
| 873 | |||
| 874 | session保存路径,默认是空 | ||
| 875 | |||
| 876 | * UseFcgi | ||
| 877 | |||
| 878 | 是否启用fastcgi,默认是false | ||
| 879 | |||
| 880 | * MaxMemory | ||
| 881 | |||
| 882 | 文件上传默认内存缓存大小,默认值是`1 << 26`(64M) | ||
| 883 | |||
| 884 | ## 第三方应用集成 | ||
| 885 | beego支持第三方应用的集成,用户可以自定义`http.Handler`,用户可以通过如下方式进行注册路由: | ||
| 886 | |||
| 887 | beego.RouterHandler("/chat/:info(.*)", sockjshandler) | ||
| 888 | |||
| 889 | sockjshandler实现了接口`http.Handler`。 | ||
| 890 | |||
| 891 | 目前在beego的example中有支持sockjs的chat例子,示例代码如下: | ||
| 892 | |||
| 893 | package main | ||
| 894 | |||
| 895 | import ( | ||
| 896 | "fmt" | ||
| 897 | "github.com/astaxie/beego" | ||
| 898 | "github.com/fzzy/sockjs-go/sockjs" | ||
| 899 | "strings" | ||
| 900 | ) | ||
| 901 | |||
| 902 | var users *sockjs.SessionPool = sockjs.NewSessionPool() | ||
| 903 | |||
| 904 | func chatHandler(s sockjs.Session) { | ||
| 905 | users.Add(s) | ||
| 906 | defer users.Remove(s) | ||
| 907 | |||
| 908 | for { | ||
| 909 | m := s.Receive() | ||
| 910 | if m == nil { | ||
| 911 | break | ||
| 912 | } | ||
| 913 | fullAddr := s.Info().RemoteAddr | ||
| 914 | addr := fullAddr[:strings.LastIndex(fullAddr, ":")] | ||
| 915 | m = []byte(fmt.Sprintf("%s: %s", addr, m)) | ||
| 916 | users.Broadcast(m) | ||
| 917 | } | ||
| 918 | } | ||
| 919 | |||
| 920 | type MainController struct { | ||
| 921 | beego.Controller | ||
| 922 | } | ||
| 923 | |||
| 924 | func (m *MainController) Get() { | ||
| 925 | m.TplNames = "index.html" | ||
| 926 | } | ||
| 927 | |||
| 928 | func main() { | ||
| 929 | conf := sockjs.NewConfig() | ||
| 930 | sockjshandler := sockjs.NewHandler("/chat", chatHandler, conf) | ||
| 931 | beego.Router("/", &MainController{}) | ||
| 932 | beego.RouterHandler("/chat/:info(.*)", sockjshandler) | ||
| 933 | beego.Run() | ||
| 934 | } | ||
| 935 | |||
| 936 | 通过上面的代码很简单的实现了一个多人的聊天室。上面这个只是一个sockjs的例子,我想通过大家自定义`http.Handler`,可以有很多种方式来进行扩展beego应用。 | ||
| 937 | |||
| 938 | ## 部署编译应用 | ||
| 939 | Go语言的应用最后编译之后是一个二进制文件,你只需要copy这个应用到服务器上,运行起来就行。beego由于带有几个静态文件、配置文件、模板文件三个目录,所以用户部署的时候需要同时copy这三个目录到相应的部署应用之下,下面以我实际的应用部署为例: | ||
| 940 | |||
| 941 | $ mkdir /opt/app/beepkg | ||
| 942 | $ cp beepkg /opt/app/beepkg | ||
| 943 | $ cp -fr views /opt/app/beepkg | ||
| 944 | $ cp -fr static /opt/app/beepkg | ||
| 945 | $ cp -fr conf /opt/app/beepkg | ||
| 946 | |||
| 947 | 这样在`/opt/app/beepkg`目录下面就会显示如下的目录结构: | ||
| 948 | |||
| 949 | . | ||
| 950 | ├── conf | ||
| 951 | │ ├── app.conf | ||
| 952 | ├── static | ||
| 953 | │ ├── css | ||
| 954 | │ ├── img | ||
| 955 | │ └── js | ||
| 956 | └── views | ||
| 957 | └── index.tpl | ||
| 958 | ├── beepkg | ||
| 959 | |||
| 960 | 这样我们就已经把我们需要的应用搬到服务器了,那么接下来就可以开始部署了,我现在服务器端用两种方式来run, | ||
| 961 | |||
| 962 | - Supervisord | ||
| 963 | |||
| 964 | 安装和配置见[Supervisord](Supervisord.md) | ||
| 965 | |||
| 966 | - nohup方式 | ||
| 967 | |||
| 968 | nohup ./beepkg & | ||
| 969 | |||
| 970 | 个人比较推荐第一种方式,可以很好的管理起来应用 | ||
| 971 | |||
| 972 | - [Introduction](README.md) | ||
| 973 | - [Step by step](Tutorial.md) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -6,7 +6,7 @@ Remember when I was writing the book about how to build web applications with Go | ... | @@ -6,7 +6,7 @@ Remember when I was writing the book about how to build web applications with Go |
| 6 | I used to use CI in PHP and tornado in Python, there are both lightweight, so they has following advantages: | 6 | I used to use CI in PHP and tornado in Python, there are both lightweight, so they has following advantages: |
| 7 | 7 | ||
| 8 | 1. Save time for handling general problems, I only need to care about logic part. | 8 | 1. Save time for handling general problems, I only need to care about logic part. |
| 9 | 2. Learn more languages by studying their source code, it's not hard to read and understand them because they are both lightweight frameworks. | 9 | 2. Learn more about languages by studying their source code, it's not hard to read and understand them because they are both lightweight frameworks. |
| 10 | 3. It's quite easy to make secondary development of these frameworks for specific purposes. | 10 | 3. It's quite easy to make secondary development of these frameworks for specific purposes. |
| 11 | 11 | ||
| 12 | Those reasons are my original intention of implementing Beego, and used two chapters in my book to introduce and design this lightweight web framework in GO. | 12 | Those reasons are my original intention of implementing Beego, and used two chapters in my book to introduce and design this lightweight web framework in GO. | ... | ... |
-
Please register or sign in to post a comment