d2e0960b by astaxie

fix the example error

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